Snap for 5381581 from 47e8fbbcee to qt-release
Change-Id: If8c8c99a59453205461f68b4ad741481bda9fdc9
This commit is contained in:
@@ -3124,6 +3124,18 @@
|
||||
|
||||
<activity android:name=".homepage.contextualcards.ContextualCardFeedbackDialog"
|
||||
android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
|
||||
|
||||
<activity
|
||||
android:name="Settings$WifiCallingDisclaimerActivity"
|
||||
android:label="@string/wifi_calling_settings_title"
|
||||
android:taskAffinity="com.android.settings">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.wifi.calling.WifiCallingDisclaimerFragment" />
|
||||
</activity>
|
||||
<!-- This is the longest AndroidManifest.xml ever. -->
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!--
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (C) 2018 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -15,10 +15,17 @@
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="32dp"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:tint="?android:attr/colorPrimary"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#000" android:pathData="M9,11.75A1.25,1.25 0 0,0 7.75,13A1.25,1.25 0 0,0 9,14.25A1.25,1.25 0 0,0 10.25,13A1.25,1.25 0 0,0 9,11.75M15,11.75A1.25,1.25 0 0,0 13.75,13A1.25,1.25 0 0,0 15,14.25A1.25,1.25 0 0,0 16.25,13A1.25,1.25 0 0,0 15,11.75M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,11.71 4,11.42 4.05,11.14C6.41,10.09 8.28,8.16 9.26,5.77C11.07,8.33 14.05,10 17.42,10C18.2,10 18.95,9.91 19.67,9.74C19.88,10.45 20,11.21 20,12C20,16.41 16.41,20 12,20Z" />
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M 12 13 C 13.1045694997 13 14 13.8954305003 14 15 C 14 16.1045694997 13.1045694997 17 12 17 C 10.8954305003 17 10 16.1045694997 10 15 C 10 13.8954305003 10.8954305003 13 12 13 Z" />
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M18.5,1C16.01,1,14,3.01,14,5.5V8H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10c0-1.1-0.9-2-2-2h-2V5.5 C16,4.12,17.12,3,18.5,3C19.88,3,21,4.12,21,5.5V6h2V5.5C23,3.01,20.99,1,18.5,1z M18,10v10H6V10H18z" />
|
||||
<path android:pathData="M0,0h24v24H0V0z" />
|
||||
</vector>
|
||||
43
res/drawable/ic_notification_alert.xml
Normal file
43
res/drawable/ic_notification_alert.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2019 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.
|
||||
-->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/back">
|
||||
<shape android:shape="oval">
|
||||
<solid
|
||||
android:color="@android:color/transparent" />
|
||||
<size
|
||||
android:height="48dp"
|
||||
android:width="48dp"/>
|
||||
<stroke android:width="1dp"
|
||||
android:color="@color/notification_alert_color"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/fore"
|
||||
android:gravity="center">
|
||||
<vector
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
<path
|
||||
android:fillColor="@color/notification_alert_color"
|
||||
android:pathData="M7.58 4.08L6.15 2.65C3.75 4.48 2.17 7.3 2.03 10.5h2c.15-2.65 1.51-4.97 3.55-6.42zm12.39 6.42h2c-.15-3.2-1.73-6.02-4.12-7.85l-1.42 1.43c2.02 1.45 3.39 3.77 3.54 6.42zM18 11c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2v-5zm-6 11c.14 0 .27-.01.4-.04.65-.14 1.18-.58 1.44-1.18.1-.24.15-.5.15-.78h-4c.01 1.1.9 2 2.01 2z"/>
|
||||
</vector>
|
||||
</item>
|
||||
</layer-list>
|
||||
43
res/drawable/ic_notification_block.xml
Normal file
43
res/drawable/ic_notification_block.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2019 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.
|
||||
-->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/back">
|
||||
<shape android:shape="oval">
|
||||
<solid
|
||||
android:color="@android:color/transparent" />
|
||||
<size
|
||||
android:height="48dp"
|
||||
android:width="48dp"/>
|
||||
<stroke android:width="1dp"
|
||||
android:color="@color/notification_block_color"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/fore"
|
||||
android:gravity="center">
|
||||
<vector
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
<path
|
||||
android:fillColor="@color/notification_block_color"
|
||||
android:pathData="M12.0,2.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0zM4.0,12.0c0.0,-4.42 3.58,-8.0 8.0,-8.0 1.85,0.0 3.5,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4.0,13.85 4.0,12.0zm8.0,8.0c-1.85,0.0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20.0,10.15 20.0,12.0c0.0,4.42 -3.58,8.0 -8.0,8.0z"/>
|
||||
</vector>
|
||||
</item>
|
||||
</layer-list>
|
||||
43
res/drawable/ic_notification_silence.xml
Normal file
43
res/drawable/ic_notification_silence.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2019 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.
|
||||
-->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/back">
|
||||
<shape android:shape="oval">
|
||||
<solid
|
||||
android:color="@android:color/transparent" />
|
||||
<size
|
||||
android:height="48dp"
|
||||
android:width="48dp"/>
|
||||
<stroke android:width="1dp"
|
||||
android:color="@color/notification_silence_color"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/fore"
|
||||
android:gravity="center">
|
||||
<vector
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
<path
|
||||
android:fillColor="@color/notification_silence_color"
|
||||
android:pathData="M20 18.69L7.84 6.14 5.27 3.49 4 4.76l2.8 2.8v.01c-.52.99-.8 2.16-.8 3.42v5l-2 2v1h13.73l2 2L21 19.72l-1-1.03zM12 22c1.11 0 2-.89 2-2h-4c0 1.11.89 2 2 2zm6-7.32V11c0-3.08-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68c-.15.03-.29.08-.42.12-.1.03-.2.07-.3.11h-.01c-.01 0-.01 0-.02.01-.23.09-.46.2-.68.31 0 0-.01 0-.01.01L18 14.68z" />
|
||||
</vector>
|
||||
</item>
|
||||
</layer-list>
|
||||
104
res/layout/notif_importance_preference.xml
Normal file
104
res/layout/notif_importance_preference.xml
Normal file
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2019 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:id="@+id/app_entities_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/block"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="33.33"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/block_icon"
|
||||
android:layout_width="@dimen/notification_importance_toggle_size"
|
||||
android:layout_height="@dimen/notification_importance_toggle_size"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_notification_block"
|
||||
android:contentDescription="@string/notification_block_title" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/notification_block_title"
|
||||
android:layout_marginTop="@dimen/notification_importance_toggle_marginTop"
|
||||
android:layout_marginBottom="@dimen/notification_importance_toggle_marginBottom"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/silence"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="33.33"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/silence_icon"
|
||||
android:layout_width="@dimen/notification_importance_toggle_size"
|
||||
android:layout_height="@dimen/notification_importance_toggle_size"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_notification_silence"
|
||||
android:contentDescription="@string/notification_silence_title" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/notification_silence_title"
|
||||
android:layout_marginTop="@dimen/notification_importance_toggle_marginTop"
|
||||
android:layout_marginBottom="@dimen/notification_importance_toggle_marginBottom"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/alert"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="33.33"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/alert_icon"
|
||||
android:layout_width="@dimen/notification_importance_toggle_size"
|
||||
android:layout_height="@dimen/notification_importance_toggle_size"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_notification_alert"
|
||||
android:contentDescription="@string/notification_alert_title" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/notification_alert_title"
|
||||
android:layout_marginTop="@dimen/notification_importance_toggle_marginTop"
|
||||
android:layout_marginBottom="@dimen/notification_importance_toggle_marginBottom"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
67
res/layout/wfc_disclaimer_fragment.xml
Normal file
67
res/layout/wfc_disclaimer_fragment.xml
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:text="@string/wfc_disclaimer_title_text" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/disclaimer_item_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
|
||||
<Button
|
||||
android:id="@+id/disagree_button"
|
||||
style="@style/DisclaimerNegativeButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/wfc_disclaimer_disagree_text" />
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/agree_button"
|
||||
style="@style/DisclaimerPositiveButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/wfc_disclaimer_agree_button_text" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
36
res/layout/wfc_simple_disclaimer_item.xml
Normal file
36
res/layout/wfc_simple_disclaimer_item.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="20dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:gravity="center_vertical">
|
||||
<TextView
|
||||
android:id="@+id/disclaimer_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Subhead" />
|
||||
<TextView
|
||||
android:id="@+id/disclaimer_desc"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@android:style/TextAppearance.Material.Body1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:layout_below="@id/disclaimer_title" />
|
||||
</RelativeLayout>
|
||||
@@ -56,7 +56,7 @@
|
||||
<color name="material_blue_700">#3367D6</color>
|
||||
<color name="material_grey_100">#f5f5f5</color>
|
||||
<color name="material_grey_200">#ffffff</color>
|
||||
<color name="switch_bar_background">#ff80868B</color>
|
||||
<color name="switch_bar_background">#757575</color>
|
||||
|
||||
<color name="message_text_incoming">#ffffffff</color>
|
||||
<color name="message_text_outgoing">#ff323232</color>
|
||||
@@ -124,6 +124,11 @@
|
||||
<color name="face_anim_particle_color_4">#fffdd835</color> <!-- Material Yellow 600 -->
|
||||
<color name="face_anim_particle_error">#ff9e9e9e</color> <!-- Material Gray 500 -->
|
||||
|
||||
<!-- notification settings -->
|
||||
<color name="notification_block_color">#ffff0000</color>
|
||||
<color name="notification_silence_color">#fbbc04</color>
|
||||
<color name="notification_alert_color">#30a751</color>
|
||||
|
||||
<!-- launcher icon color -->
|
||||
<color name="icon_launcher_setting_color">@*android:color/accent_device_default_light</color>
|
||||
|
||||
|
||||
@@ -68,6 +68,9 @@
|
||||
<dimen name="notification_app_icon_size">64dp</dimen>
|
||||
<dimen name="notification_app_icon_badge_size">20dp</dimen>
|
||||
<dimen name="notification_app_icon_badge_margin">4dp</dimen>
|
||||
<dimen name="notification_importance_toggle_size">48dp</dimen>
|
||||
<dimen name="notification_importance_toggle_marginTop">8dp</dimen>
|
||||
<dimen name="notification_importance_toggle_marginBottom">16dp</dimen>
|
||||
<dimen name="zen_schedule_rule_checkbox_padding">7dp</dimen>
|
||||
<dimen name="zen_schedule_day_margin">17dp</dimen>
|
||||
|
||||
|
||||
@@ -3022,14 +3022,14 @@
|
||||
<string name="status_prl_version">PRL version</string>
|
||||
<!-- About phone screen, title for MEID for multi-sim devices -->
|
||||
<string name="meid_multi_sim">MEID (sim slot %1$d)</string>
|
||||
<!-- The status text when both Wi-Fi scanning and Bluetooth scanning are on. [CHAR LIMIT=120] -->
|
||||
<string name="scanning_status_text_wifi_on_ble_on">Both Wi\u2011Fi and Bluetooth are allowed to determine location</string>
|
||||
<!-- The status text when Wi-Fi scanning is on and Bluetooth scanning are off. [CHAR LIMIT=120] -->
|
||||
<string name="scanning_status_text_wifi_on_ble_off">Only Wi\u2011Fi is allowed to determine location</string>
|
||||
<!-- The status text when Wi-Fi scanning is off and Bluetooth scanning are on. [CHAR LIMIT=120] -->
|
||||
<string name="scanning_status_text_wifi_off_ble_on">Only Bluetooth is allowed to determine location</string>
|
||||
<!-- The status text when both Wi-Fi scanning and Bluetooth scanning are off. [CHAR LIMIT=120] -->
|
||||
<string name="scanning_status_text_wifi_off_ble_off">Neither Wi\u2011Fi nor Bluetooth is allowed to determine location</string>
|
||||
<!-- The status text when both Wi-Fi scanning and Bluetooth scanning are on. [CHAR LIMIT=100] -->
|
||||
<string name="scanning_status_text_wifi_on_ble_on">Both Wi\u2011Fi and Bluetooth scanning are on</string>
|
||||
<!-- The status text when Wi-Fi scanning is on and Bluetooth scanning are off. [CHAR LIMIT=100] -->
|
||||
<string name="scanning_status_text_wifi_on_ble_off">Wi\u2011Fi scanning is on, Bluetooth scanning is off</string>
|
||||
<!-- The status text when Wi-Fi scanning is off and Bluetooth scanning are on. [CHAR LIMIT=100] -->
|
||||
<string name="scanning_status_text_wifi_off_ble_on">Bluetooth scanning is on, Wi\u2011Fi scanning is off</string>
|
||||
<!-- The status text when both Wi-Fi scanning and Bluetooth scanning are off. [CHAR LIMIT=100] -->
|
||||
<string name="scanning_status_text_wifi_off_ble_off">Both Wi\u2011Fi and Bluetooth scanning are off</string>
|
||||
<!-- About phone, status item title. The phone MEID number of the current LTE/CDMA device. [CHAR LIMIT=30] -->
|
||||
<string name="status_meid_number">MEID</string>
|
||||
<!-- About phone, status item title. The ICCID of the current LTE device. [CHAR LIMIT=30] -->
|
||||
@@ -3754,13 +3754,25 @@
|
||||
<string name="location_app_level_permissions">App permission</string>
|
||||
<!-- Summary for app permission on Location settings page when location is off [CHAR LIMIT=NONE] -->
|
||||
<string name="location_app_permission_summary_location_off">Location is off</string>
|
||||
<!-- Summary for Location settings when location is on, explaining how many apps have location permission [CHAR LIMIT=NONE]-->
|
||||
<!--
|
||||
Summary for Location settings when location is on, explaining how many apps have unlimited
|
||||
location permission.
|
||||
|
||||
"Unlimited access" means the app can access the device location even when it's not being used
|
||||
(on background), while "limited" means the app can only access the device location when the user
|
||||
is using it (foreground only).
|
||||
|
||||
Please note that the distinction between singular and plural of this sentence only depends on
|
||||
the quantity of "background_location_app_count" ("has" vs "have"). The quantity of
|
||||
"total_location_app_count" is almost always greater than 1, so "apps" is always in plural form.
|
||||
|
||||
[CHAR LIMIT=NONE]-->
|
||||
<plurals name="location_app_permission_summary_location_on">
|
||||
<item quantity="one">
|
||||
<xliff:g id="background_location_app_count">%1$d</xliff:g>
|
||||
of
|
||||
<xliff:g id="total_location_app_count">%2$d</xliff:g>
|
||||
app has unlimited access</item>
|
||||
apps has unlimited access</item>
|
||||
<item quantity="other">
|
||||
<xliff:g id="background_location_app_count">%1$d</xliff:g>
|
||||
of
|
||||
@@ -3771,8 +3783,12 @@
|
||||
<string name="location_category_recent_location_access">Recent location access</string>
|
||||
<!-- [CHAR LIMIT=30] Location settings screen, button to bring the user to view the details of recent location access -->
|
||||
<string name="location_recent_location_access_view_details">View details</string>
|
||||
<!-- Location settings screen, displayed when there's no recent app accessing location -->
|
||||
<!-- Location settings screen, displayed when there's no recent app accessing location
|
||||
(for TV) [CHAR LIMIT=100] -->
|
||||
<string name="location_no_recent_apps">No apps have requested location recently</string>
|
||||
<!-- Location settings screen, displayed when there's no recent app accessing location
|
||||
(for phones and tablets) [CHAR LIMIT=100] -->
|
||||
<string name="location_no_recent_accesses">No apps recently accessed location</string>
|
||||
<!-- [CHAR LIMIT=30] Location settings screen, recent location requests high battery use-->
|
||||
<string name="location_high_battery_use">High battery use</string>
|
||||
<!-- [CHAR LIMIT=30] Location settings screen, recent location requests low battery use-->
|
||||
@@ -7771,7 +7787,7 @@
|
||||
summary on the channel page-->
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance title: min importance level title -->
|
||||
<string name="notification_importance_min_title">Low</string>
|
||||
<string name="notification_importance_min_title">Minimize</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance title: low importance level title -->
|
||||
<string name="notification_importance_low_title">Medium</string>
|
||||
@@ -7780,7 +7796,16 @@
|
||||
<string name="notification_importance_default_title">High</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance title: high importance level title -->
|
||||
<string name="notification_importance_high_title">Urgent</string>
|
||||
<string name="notification_importance_high_title">Pop on screen</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance title -->
|
||||
<string name="notification_block_title">Block</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance title -->
|
||||
<string name="notification_silence_title">Show silently</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance title -->
|
||||
<string name="notification_alert_title">Alert</string>
|
||||
|
||||
<!-- [CHAR LIMIT=40] Notification importance title. This setting controls how notifications in older apps may alert the user (eg, sound, visual, vibrate). -->
|
||||
<string name="allow_interruption">Allow interruptions</string>
|
||||
@@ -10758,8 +10783,17 @@
|
||||
<!-- Summary for represent which device is playing media [CHAR LIMIT=NONE] -->
|
||||
<string name="media_output_panel_summary_of_playing_device">Currently playing on <xliff:g id="device_name" example="Bose headphone">%1$s</xliff:g></string>
|
||||
|
||||
<!-- Label for the title on wfc disclaimer fragment. [CHAR LIMIT=40] -->
|
||||
<string name="wfc_disclaimer_title_text">Important information</string>
|
||||
|
||||
<!-- Label for the agree button on wfc disclaimer fragment. [CHAR LIMIT=30] -->
|
||||
<string name="wfc_disclaimer_agree_button_text">CONTINUE</string>
|
||||
|
||||
<!-- Label for the disagree button on wfc disclaimer fragment. [CHAR LIMIT=30] -->
|
||||
<string name="wfc_disclaimer_disagree_text">NO THANKS</string>
|
||||
|
||||
<!-- Message for forget passpoint dialog [CHAR LIMIT=none] -->
|
||||
<string name="forget_passpoint_dialog_message">Your subscription with this provider may be cancelled. Recurring subscriptions will not be cancelled. For more information, check with your provider.</string>
|
||||
<string name="forget_passpoint_dialog_message">You may lose access to any remaining time or data. Check with your provider before removing.</string>
|
||||
|
||||
<!-- Keywords for Content Capture feature [CHAR_LIMIT=32] -->
|
||||
<string name="keywords_content_capture">content capture</string>
|
||||
@@ -10767,5 +10801,4 @@
|
||||
<string name="content_capture">Content Capture</string>
|
||||
<!-- Description of the 'Content Capture' feature toggle in the Settings -> Privacy screen [CHAR LIMIT=NONE]-->
|
||||
<string name="content_capture_summary">Allow Android to save information seen on your screen or heard in video or audio content. Android makes helpful suggestions based on your device activity.</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -520,4 +520,17 @@
|
||||
<!-- Padding between content and the start icon is 8dp. -->
|
||||
<item name="contentStartPadding">8dp</item>
|
||||
</style>
|
||||
|
||||
<style name="DisclaimerPositiveButton" parent="@style/SudGlifButton.Primary">
|
||||
<item name="android:layout_margin">16dp</item>
|
||||
<item name="android:paddingStart">8dp</item>
|
||||
<item name="android:paddingEnd">8dp</item>
|
||||
</style>
|
||||
|
||||
<style name="DisclaimerNegativeButton" parent="@style/SudGlifButton.Secondary">
|
||||
<item name="android:layout_margin">16dp</item>
|
||||
<item name="android:paddingStart">8dp</item>
|
||||
<item name="android:paddingEnd">8dp</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
android:order="1001"
|
||||
settings:restrictedSwitchSummary="@string/enabled_by_admin" />
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="bubble"
|
||||
android:key="bubble_pref"
|
||||
android:title="@string/notification_bubbles_title"
|
||||
android:order="1002"
|
||||
settings:restrictedSwitchSummary="@string/enabled_by_admin" />
|
||||
|
||||
@@ -25,11 +25,6 @@
|
||||
android:order="1"
|
||||
android:layout="@layout/settings_entity_header" />
|
||||
|
||||
<com.android.settingslib.widget.LayoutPreference
|
||||
android:key="block"
|
||||
android:order="2"
|
||||
android:layout="@layout/styled_switch_bar" />
|
||||
|
||||
<!-- Importance toggle -->
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="allow_sound"
|
||||
@@ -38,10 +33,23 @@
|
||||
android:summary="@string/allow_interruption_summary" />
|
||||
|
||||
<!-- Importance -->
|
||||
<com.android.settings.RestrictedListPreference
|
||||
<com.android.settings.notification.ImportancePreference
|
||||
android:key="importance"
|
||||
android:order="10"
|
||||
android:title="@string/notification_importance_title" />
|
||||
android:order="4"
|
||||
android:title="@string/notification_importance_title"
|
||||
settings:allowDividerBelow="true"/>
|
||||
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="min_importance"
|
||||
android:order="5"
|
||||
settings:allowDividerAbove="true"
|
||||
android:title="@string/notification_importance_min_title"/>
|
||||
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="high_importance"
|
||||
android:order="6"
|
||||
settings:allowDividerAbove="true"
|
||||
android:title="@string/notification_importance_high_title"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="channel_advanced"
|
||||
@@ -87,7 +95,7 @@
|
||||
settings:restrictedSwitchSummary="@string/enabled_by_admin"/>
|
||||
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="bubble"
|
||||
android:key="bubble_pref"
|
||||
android:title="@string/notification_bubbles_title"
|
||||
android:order="16"
|
||||
settings:restrictedSwitchSummary="@string/enabled_by_admin" />
|
||||
@@ -113,6 +121,7 @@
|
||||
|
||||
<com.android.settings.notification.NotificationFooterPreference
|
||||
android:key="block_desc"
|
||||
android:order="110"/>
|
||||
android:order="110"
|
||||
settings:allowDividerAbove="false"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:key="mobile_network_list_screen"
|
||||
android:title="@string/network_settings_title">
|
||||
|
||||
<Preference
|
||||
android:key="add_more"
|
||||
settings:isPreferenceVisible="false"
|
||||
android:title="@string/mobile_network_list_add_more"
|
||||
android:icon="@drawable/ic_menu_add"
|
||||
android:order="100" >
|
||||
|
||||
@@ -26,6 +26,11 @@
|
||||
android:order="-10000"
|
||||
settings:allowDividerBelow="true"/>
|
||||
|
||||
<com.android.settings.datausage.DataUsageSummaryPreference
|
||||
android:key="status_header"
|
||||
android:selectable="false"
|
||||
settings:isPreferenceVisible="false"/>
|
||||
|
||||
<!-- Buttons -->
|
||||
<com.android.settingslib.widget.ActionButtonsPreference
|
||||
android:key="buttons"
|
||||
|
||||
@@ -457,6 +457,13 @@ public class RadioInfo extends Activity {
|
||||
imsWfcProvisionedSwitch = (Switch) findViewById(R.id.wfc_provisioned_switch);
|
||||
eabProvisionedSwitch = (Switch) findViewById(R.id.eab_provisioned_switch);
|
||||
|
||||
if (!ImsManager.isImsSupportedOnDevice(phone.getContext())) {
|
||||
imsVolteProvisionedSwitch.setVisibility(View.GONE);
|
||||
imsVtProvisionedSwitch.setVisibility(View.GONE);
|
||||
imsWfcProvisionedSwitch.setVisibility(View.GONE);
|
||||
eabProvisionedSwitch.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
cbrsDataSwitch = (Switch) findViewById(R.id.cbrs_data_switch);
|
||||
cbrsDataSwitch.setVisibility(isCbrsSupported() ? View.VISIBLE : View.GONE);
|
||||
|
||||
@@ -631,8 +638,10 @@ public class RadioInfo extends Activity {
|
||||
R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback);
|
||||
menu.add(1, MENU_ITEM_VIEW_SDN, 0,
|
||||
R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback);
|
||||
menu.add(1, MENU_ITEM_GET_IMS_STATUS,
|
||||
0, R.string.radioInfo_menu_getIMS).setOnMenuItemClickListener(mGetImsStatus);
|
||||
if (ImsManager.isImsSupportedOnDevice(phone.getContext())) {
|
||||
menu.add(1, MENU_ITEM_GET_IMS_STATUS,
|
||||
0, R.string.radioInfo_menu_getIMS).setOnMenuItemClickListener(mGetImsStatus);
|
||||
}
|
||||
menu.add(1, MENU_ITEM_TOGGLE_DATA,
|
||||
0, R.string.radio_info_data_connection_disable).setOnMenuItemClickListener(mToggleData);
|
||||
return true;
|
||||
@@ -1384,6 +1393,9 @@ public class RadioInfo extends Activity {
|
||||
}
|
||||
|
||||
private void updateImsProvisionedState() {
|
||||
if (!ImsManager.isImsSupportedOnDevice(phone.getContext())) {
|
||||
return;
|
||||
}
|
||||
log("updateImsProvisionedState isImsVolteProvisioned()=" + isImsVolteProvisioned());
|
||||
//delightful hack to prevent on-checked-changed calls from
|
||||
//actually forcing the ims provisioning to its transient/current value.
|
||||
|
||||
@@ -157,20 +157,9 @@ public class ResetNetworkConfirm extends InstrumentedFragment {
|
||||
SubscriptionManager.getPhoneId(mSubId)).factoryReset();
|
||||
restoreDefaultApn(context);
|
||||
esimFactoryReset(context, context.getPackageName());
|
||||
// There has been issues when Sms raw table somehow stores orphan
|
||||
// fragments. They lead to garbled message when new fragments come
|
||||
// in and combied with those stale ones. In case this happens again,
|
||||
// user can reset all network settings which will clean up this table.
|
||||
cleanUpSmsRawTable(context);
|
||||
}
|
||||
};
|
||||
|
||||
private void cleanUpSmsRawTable(Context context) {
|
||||
ContentResolver resolver = context.getContentResolver();
|
||||
Uri uri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete");
|
||||
resolver.delete(uri, null, null);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void esimFactoryReset(Context context, String packageName) {
|
||||
if (mEraseEsim) {
|
||||
|
||||
@@ -159,6 +159,7 @@ public class Settings extends SettingsActivity {
|
||||
public static class WebViewAppPickerActivity extends SettingsActivity { /* empty */ }
|
||||
public static class AdvancedConnectedDeviceActivity extends SettingsActivity { /* empty */ }
|
||||
public static class BluetoothDeviceDetailActivity extends SettingsActivity { /* empty */ }
|
||||
public static class WifiCallingDisclaimerActivity extends SettingsActivity { /* empty */ }
|
||||
|
||||
// Top level categories for new IA
|
||||
public static class NetworkDashboardActivity extends SettingsActivity {}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.accounts;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@@ -64,11 +65,13 @@ public class AvatarViewMixin implements LifecycleObserver {
|
||||
private final Context mContext;
|
||||
private final ImageView mAvatarView;
|
||||
private final MutableLiveData<Bitmap> mAvatarImage;
|
||||
private final ActivityManager mActivityManager;
|
||||
|
||||
private String mAccountName;
|
||||
|
||||
public AvatarViewMixin(SettingsHomepageActivity activity, ImageView avatarView) {
|
||||
mContext = activity.getApplicationContext();
|
||||
mActivityManager = mContext.getSystemService(ActivityManager.class);
|
||||
mAvatarView = avatarView;
|
||||
mAvatarView.setOnClickListener(v -> {
|
||||
Intent intent;
|
||||
@@ -114,7 +117,11 @@ public class AvatarViewMixin implements LifecycleObserver {
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_START)
|
||||
public void onStart() {
|
||||
if (!mContext.getResources().getBoolean(R.bool.config_show_avatar_in_homepage)) {
|
||||
Log.d(TAG, "Feature disabled. Skipping");
|
||||
Log.d(TAG, "Feature disabled by config. Skipping");
|
||||
return;
|
||||
}
|
||||
if (mActivityManager.isLowRamDevice()) {
|
||||
Log.d(TAG, "Feature disabled on low ram device. Skipping");
|
||||
return;
|
||||
}
|
||||
if (hasAccount()) {
|
||||
|
||||
@@ -58,9 +58,14 @@ public class FaceEnrollAccessibilityToggle extends LinearLayout {
|
||||
a.recycle();
|
||||
}
|
||||
mSwitch = findViewById(R.id.toggle);
|
||||
mSwitch.setChecked(false);
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
return mSwitch.isChecked();
|
||||
}
|
||||
|
||||
public void setChecked(boolean checked) {
|
||||
mSwitch.setChecked(checked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
|
||||
final LinearLayout accessibilityLayout = findViewById(R.id.accessibility_layout);
|
||||
final Button accessibilityButton = findViewById(R.id.accessibility_button);
|
||||
accessibilityButton.setOnClickListener(view -> {
|
||||
mSwitchDiversity.setChecked(true);
|
||||
accessibilityButton.setVisibility(View.INVISIBLE);
|
||||
accessibilityLayout.setVisibility(View.VISIBLE);
|
||||
});
|
||||
@@ -177,7 +178,7 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
|
||||
} else {
|
||||
intent.setClass(this, FaceEnrollEnrolling.class);
|
||||
}
|
||||
intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, mSwitchDiversity.isChecked());
|
||||
intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
|
||||
WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@@ -26,4 +26,7 @@ public class FeatureFlags {
|
||||
public static final String NETWORK_INTERNET_V2 = "settings_network_and_internet_v2";
|
||||
public static final String SLICE_INJECTION = "settings_slice_injection";
|
||||
public static final String MAINLINE_MODULE = "settings_mainline_module";
|
||||
public static final String WIFI_DETAILS_SAVED_SCREEN = "settings_wifi_details_saved_screen";
|
||||
public static final String WIFI_DETAILS_DATAUSAGE_HEADER =
|
||||
"settings_wifi_details_datausage_header";
|
||||
}
|
||||
|
||||
@@ -135,6 +135,7 @@ import com.android.settings.wifi.ConfigureWifiSettings;
|
||||
import com.android.settings.wifi.WifiAPITest;
|
||||
import com.android.settings.wifi.WifiInfo;
|
||||
import com.android.settings.wifi.WifiSettings;
|
||||
import com.android.settings.wifi.calling.WifiCallingDisclaimerFragment;
|
||||
import com.android.settings.wifi.calling.WifiCallingSettings;
|
||||
import com.android.settings.wifi.p2p.WifiP2pSettings;
|
||||
import com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings;
|
||||
@@ -260,6 +261,7 @@ public class SettingsGateway {
|
||||
ConnectedDeviceDashboardFragment.class.getName(),
|
||||
UsbDetailsFragment.class.getName(),
|
||||
AppAndNotificationDashboardFragment.class.getName(),
|
||||
WifiCallingDisclaimerFragment.class.getName(),
|
||||
AccountDashboardFragment.class.getName(),
|
||||
EnterprisePrivacySettings.class.getName(),
|
||||
WebViewAppPicker.class.getName(),
|
||||
|
||||
@@ -69,6 +69,8 @@ public class DataUsageSummaryPreference extends Preference {
|
||||
private boolean mDefaultTextColorSet;
|
||||
private int mDefaultTextColor;
|
||||
private int mNumPlans;
|
||||
/** The specified un-initialized value for cycle time */
|
||||
private final long CYCLE_TIME_UNINITIAL_VALUE = 0;
|
||||
/** The ending time of the billing cycle in milliseconds since epoch. */
|
||||
private long mCycleEndTimeMs;
|
||||
/** The time of the last update in standard milliseconds since the epoch */
|
||||
@@ -94,6 +96,7 @@ public class DataUsageSummaryPreference extends Preference {
|
||||
/** WiFi only mode */
|
||||
private boolean mWifiMode;
|
||||
private String mUsagePeriod;
|
||||
private boolean mSingleWifi; // Shows only one specified WiFi network usage
|
||||
|
||||
public DataUsageSummaryPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@@ -142,9 +145,10 @@ public class DataUsageSummaryPreference extends Preference {
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
void setWifiMode(boolean isWifiMode, String usagePeriod) {
|
||||
void setWifiMode(boolean isWifiMode, String usagePeriod, boolean isSingleWifi) {
|
||||
mWifiMode = isWifiMode;
|
||||
mUsagePeriod = usagePeriod;
|
||||
mSingleWifi = isSingleWifi;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
@@ -171,7 +175,16 @@ public class DataUsageSummaryPreference extends Preference {
|
||||
Button launchButton = (Button) holder.findViewById(R.id.launch_mdp_app_button);
|
||||
TextView limitInfo = (TextView) holder.findViewById(R.id.data_limits);
|
||||
|
||||
if (mWifiMode) {
|
||||
if (mWifiMode && mSingleWifi) {
|
||||
updateCycleTimeText(holder);
|
||||
|
||||
usageTitle.setVisibility(View.GONE);
|
||||
launchButton.setVisibility(View.GONE);
|
||||
carrierInfo.setVisibility(View.GONE);
|
||||
|
||||
limitInfo.setVisibility(TextUtils.isEmpty(mLimitInfoText) ? View.GONE : View.VISIBLE);
|
||||
limitInfo.setText(mLimitInfoText);
|
||||
} else if (mWifiMode) {
|
||||
usageTitle.setText(R.string.data_usage_wifi_title);
|
||||
usageTitle.setVisibility(View.VISIBLE);
|
||||
TextView cycleTime = (TextView) holder.findViewById(R.id.cycle_left_time);
|
||||
@@ -265,6 +278,13 @@ public class DataUsageSummaryPreference extends Preference {
|
||||
private void updateCycleTimeText(PreferenceViewHolder holder) {
|
||||
TextView cycleTime = (TextView) holder.findViewById(R.id.cycle_left_time);
|
||||
|
||||
// Takes zero as a special case which value is never set.
|
||||
if (mCycleEndTimeMs == CYCLE_TIME_UNINITIAL_VALUE) {
|
||||
cycleTime.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
|
||||
cycleTime.setVisibility(View.VISIBLE);
|
||||
long millisLeft = mCycleEndTimeMs - System.currentTimeMillis();
|
||||
if (millisLeft <= 0) {
|
||||
cycleTime.setText(getContext().getString(R.string.billing_cycle_none_left));
|
||||
|
||||
@@ -65,10 +65,10 @@ public class DataUsageSummaryPreferenceController extends BasePreferenceControll
|
||||
private final EntityHeaderController mEntityHeaderController;
|
||||
private final Lifecycle mLifecycle;
|
||||
private final PreferenceFragmentCompat mFragment;
|
||||
private final DataUsageController mDataUsageController;
|
||||
private final DataUsageInfoController mDataInfoController;
|
||||
protected final DataUsageController mDataUsageController;
|
||||
protected final DataUsageInfoController mDataInfoController;
|
||||
private final NetworkTemplate mDefaultTemplate;
|
||||
private final NetworkPolicyEditor mPolicyEditor;
|
||||
protected final NetworkPolicyEditor mPolicyEditor;
|
||||
private final int mDataUsageTemplate;
|
||||
private final boolean mHasMobileData;
|
||||
private final SubscriptionManager mSubscriptionManager;
|
||||
@@ -200,11 +200,13 @@ public class DataUsageSummaryPreferenceController extends BasePreferenceControll
|
||||
if (DataUsageUtils.hasSim(mActivity)) {
|
||||
info = mDataUsageController.getDataUsageInfo(mDefaultTemplate);
|
||||
mDataInfoController.updateDataLimit(info, mPolicyEditor.getPolicy(mDefaultTemplate));
|
||||
summaryPreference.setWifiMode(/* isWifiMode */ false, /* usagePeriod */ null);
|
||||
summaryPreference.setWifiMode(/* isWifiMode */ false,
|
||||
/* usagePeriod */ null, /* isSingleWifi */ false);
|
||||
} else {
|
||||
info = mDataUsageController.getDataUsageInfo(
|
||||
NetworkTemplate.buildTemplateWifiWildcard());
|
||||
summaryPreference.setWifiMode(/* isWifiMode */ true, /* usagePeriod */ info.period);
|
||||
summaryPreference.setWifiMode(/* isWifiMode */ true, /* usagePeriod */
|
||||
info.period, /* isSingleWifi */ false);
|
||||
summaryPreference.setLimitInfo(null);
|
||||
summaryPreference.setUsageNumbers(info.usageLevel,
|
||||
/* dataPlanSize */ -1L,
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.datausage;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.net.NetworkTemplate;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.text.format.Formatter;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.net.DataUsageController;
|
||||
|
||||
/**
|
||||
* The controller displays a data usage chart for the specified Wi-Fi network.
|
||||
*/
|
||||
public class WifiDataUsageSummaryPreferenceController extends DataUsageSummaryPreferenceController {
|
||||
final String mNetworkId;
|
||||
|
||||
public WifiDataUsageSummaryPreferenceController(Activity activity,
|
||||
Lifecycle lifecycle, PreferenceFragmentCompat fragment, CharSequence networkId) {
|
||||
super(activity, lifecycle, fragment, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
|
||||
if (networkId == null) {
|
||||
mNetworkId = null;
|
||||
} else {
|
||||
mNetworkId = String.valueOf(networkId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
if (preference == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final DataUsageSummaryPreference mPreference = (DataUsageSummaryPreference) preference;
|
||||
// TODO(b/126299427): Currently gets data usage of whole Wi-Fi networks, but should get
|
||||
// specified one.
|
||||
final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(mNetworkId);
|
||||
final DataUsageController.DataUsageInfo info = mDataUsageController.getDataUsageInfo(
|
||||
template);
|
||||
mDataInfoController.updateDataLimit(info, mPolicyEditor.getPolicy(template));
|
||||
|
||||
mPreference.setWifiMode(/* isWifiMode */ true, /* usagePeriod */
|
||||
info.period, /* isSingleWifi */ true);
|
||||
mPreference.setChartEnabled(true);
|
||||
// Treats Wi-Fi network as unlimited network, which has same usage level and limited level.
|
||||
mPreference.setUsageNumbers(info.usageLevel, info.usageLevel, /* hasMobileData */ false);
|
||||
|
||||
// TODO(b/126142293): Passpoint Wi-Fi should have limit of data usage and time remaining
|
||||
mPreference.setProgress(100);
|
||||
mPreference.setLabels(Formatter.formatFileSize(mContext, /* sizeBytes */ 0),
|
||||
DataUsageUtils.formatDataUsage(mContext, info.usageLevel));
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.homepage;
|
||||
|
||||
import android.animation.LayoutTransition;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
@@ -53,7 +54,10 @@ public class SettingsHomepageActivity extends SettingsBaseActivity {
|
||||
final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView);
|
||||
getLifecycle().addObserver(avatarViewMixin);
|
||||
|
||||
showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
|
||||
if (!getSystemService(ActivityManager.class).isLowRamDevice()) {
|
||||
// Only allow contextual feature on high ram devices.
|
||||
showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
|
||||
}
|
||||
showFragment(new TopLevelSettings(), R.id.main_content);
|
||||
((FrameLayout) findViewById(R.id.main_content))
|
||||
.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
|
||||
|
||||
@@ -67,7 +67,8 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>
|
||||
|
||||
@VisibleForTesting
|
||||
Uri mNotifyUri;
|
||||
private Context mContext;
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
ContextualCardLoader(Context context) {
|
||||
super(context);
|
||||
|
||||
@@ -109,13 +109,13 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
|
||||
}
|
||||
}
|
||||
|
||||
void loadContextualCards(ContextualCardsFragment fragment) {
|
||||
void loadContextualCards(LoaderManager loaderManager) {
|
||||
mStartTime = System.currentTimeMillis();
|
||||
final CardContentLoaderCallbacks cardContentLoaderCallbacks =
|
||||
new CardContentLoaderCallbacks(mContext);
|
||||
cardContentLoaderCallbacks.setListener(this);
|
||||
// Use the cached data when navigating back to the first page and upon screen rotation.
|
||||
LoaderManager.getInstance(fragment).initLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
|
||||
loaderManager.initLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
|
||||
cardContentLoaderCallbacks);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,16 +19,19 @@ package com.android.settings.homepage.contextualcards;
|
||||
import static com.android.settings.homepage.contextualcards.ContextualCardsAdapter.SPAN_COUNT;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.InstrumentedFragment;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
|
||||
public class ContextualCardsFragment extends InstrumentedFragment {
|
||||
|
||||
@@ -42,14 +45,19 @@ public class ContextualCardsFragment extends InstrumentedFragment {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mContextualCardManager = new ContextualCardManager(getContext(), getSettingsLifecycle(),
|
||||
final Context context = getContext();
|
||||
if (savedInstanceState == null) {
|
||||
FeatureFactory.getFactory(context).getSlicesFeatureProvider().newUiSession();
|
||||
}
|
||||
mContextualCardManager = new ContextualCardManager(context, getSettingsLifecycle(),
|
||||
savedInstanceState);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
mContextualCardManager.loadContextualCards(this);
|
||||
mContextualCardManager.loadContextualCards(LoaderManager.getInstance(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -74,6 +74,7 @@ public class RecentLocationAccessPreferenceController extends AbstractPreference
|
||||
mController = AppEntitiesHeaderController.newInstance(mContext, view)
|
||||
.setHeaderTitleRes(R.string.location_category_recent_location_access)
|
||||
.setHeaderDetailsRes(R.string.location_recent_location_access_view_details)
|
||||
.setHeaderEmptyRes(R.string.location_no_recent_accesses)
|
||||
.setHeaderDetailsClickListener((View v) -> {
|
||||
final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE);
|
||||
intent.putExtra(Intent.EXTRA_PERMISSION_NAME,
|
||||
@@ -100,14 +101,20 @@ public class RecentLocationAccessPreferenceController extends AbstractPreference
|
||||
.setIcon(access.icon)
|
||||
.setTitle(access.label)
|
||||
.setSummary(access.contentDescription)
|
||||
.setOnClickListener((v) -> {
|
||||
final Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
|
||||
intent.putExtra(Intent.EXTRA_PERMISSION_NAME,
|
||||
Manifest.permission_group.LOCATION);
|
||||
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, access.packageName);
|
||||
intent.putExtra(Intent.EXTRA_USER, access.userHandle);
|
||||
mContext.startActivity(intent);
|
||||
})
|
||||
.build();
|
||||
mController.setAppEntity(i, appEntityInfo);
|
||||
}
|
||||
for (; i < MAXIMUM_APP_COUNT; i++) {
|
||||
mController.removeAppEntity(i);
|
||||
}
|
||||
} else {
|
||||
// If there's no item to display, add a "No recent apps" item.
|
||||
}
|
||||
mController.apply();
|
||||
}
|
||||
|
||||
@@ -24,14 +24,10 @@ import android.content.Intent;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.euicc.EuiccManager;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.lifecycle.OnLifecycleEvent;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.network.telephony.MobileNetworkActivity;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
@@ -39,6 +35,12 @@ import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.lifecycle.OnLifecycleEvent;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
/**
|
||||
* This populates the entries on a page which lists all available mobile subscriptions. Each entry
|
||||
* has the name of the subscription with some subtext giving additional detail, and clicking on the
|
||||
@@ -48,6 +50,9 @@ public class MobileNetworkListController extends AbstractPreferenceController im
|
||||
LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
|
||||
private static final String TAG = "MobileNetworkListCtlr";
|
||||
|
||||
@VisibleForTesting
|
||||
static final String KEY_ADD_MORE = "add_more";
|
||||
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
private SubscriptionsChangeListener mChangeListener;
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
@@ -76,6 +81,8 @@ public class MobileNetworkListController extends AbstractPreferenceController im
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPreferenceScreen = screen;
|
||||
final EuiccManager euiccManager = mContext.getSystemService(EuiccManager.class);
|
||||
mPreferenceScreen.findPreference(KEY_ADD_MORE).setVisible(euiccManager.isEnabled());
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -93,7 +100,7 @@ public class MobileNetworkListController extends AbstractPreferenceController im
|
||||
final List<SubscriptionInfo> subscriptions = SubscriptionUtil.getAvailableSubscriptions(
|
||||
mSubscriptionManager);
|
||||
for (SubscriptionInfo info : subscriptions) {
|
||||
int subId = info.getSubscriptionId();
|
||||
final int subId = info.getSubscriptionId();
|
||||
Preference pref = existingPreferences.remove(subId);
|
||||
if (pref == null) {
|
||||
pref = new Preference(mPreferenceScreen.getContext());
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.settings.network;
|
||||
|
||||
import static android.telephony.TelephonyManager.MultiSimVariants.UNKNOWN;
|
||||
|
||||
import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
|
||||
import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
|
||||
|
||||
@@ -25,7 +23,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.telephony.euicc.EuiccManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
@@ -52,7 +49,6 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
|
||||
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
private SubscriptionsChangeListener mChangeListener;
|
||||
private TelephonyManager mTelephonyMgr;
|
||||
private EuiccManager mEuiccManager;
|
||||
private AddPreference mPreference;
|
||||
|
||||
@@ -74,7 +70,6 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
|
||||
public MobileNetworkSummaryController(Context context, Lifecycle lifecycle) {
|
||||
super(context);
|
||||
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
|
||||
mTelephonyMgr = mContext.getSystemService(TelephonyManager.class);
|
||||
mEuiccManager = mContext.getSystemService(EuiccManager.class);
|
||||
if (lifecycle != null) {
|
||||
mChangeListener = new SubscriptionsChangeListener(context, this);
|
||||
@@ -124,48 +119,43 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
|
||||
private boolean shouldShowAddButton() {
|
||||
// The add button should only show up if the device is in multi-sim mode and the eSIM
|
||||
// manager is enabled.
|
||||
return mTelephonyMgr.getMultiSimConfiguration() != UNKNOWN && mEuiccManager.isEnabled();
|
||||
}
|
||||
|
||||
private void update() {
|
||||
if (mPreference == null) {
|
||||
return;
|
||||
}
|
||||
final boolean showAddButton = shouldShowAddButton();
|
||||
refreshSummary(mPreference);
|
||||
if (!showAddButton) {
|
||||
mPreference.setOnAddClickListener(null);
|
||||
} else {
|
||||
mPreference.setAddWidgetEnabled(!mChangeListener.isAirplaneModeOn());
|
||||
mPreference.setOnAddClickListener(p -> {
|
||||
startAddSimFlow();
|
||||
});
|
||||
}
|
||||
final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
|
||||
mSubscriptionManager);
|
||||
mPreference.setOnPreferenceClickListener(null);
|
||||
mPreference.setOnAddClickListener(null);
|
||||
mPreference.setFragment(null);
|
||||
mPreference.setEnabled(!mChangeListener.isAirplaneModeOn());
|
||||
|
||||
final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
|
||||
mSubscriptionManager);
|
||||
|
||||
if (subs.isEmpty()) {
|
||||
if (showAddButton) {
|
||||
mPreference.setEnabled(false);
|
||||
} else if (mEuiccManager.isEnabled()) {
|
||||
if (mEuiccManager.isEnabled()) {
|
||||
mPreference.setOnPreferenceClickListener((Preference pref) -> {
|
||||
startAddSimFlow();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
} else if (subs.size() == 1) {
|
||||
mPreference.setOnPreferenceClickListener((Preference pref) -> {
|
||||
final Intent intent = new Intent(mContext, MobileNetworkActivity.class);
|
||||
mContext.startActivity(intent);
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
mPreference.setFragment(MobileNetworkListFragment.class.getCanonicalName());
|
||||
// We have one or more existing subscriptions, so we want the plus button if eSIM is
|
||||
// supported.
|
||||
if (mEuiccManager.isEnabled()) {
|
||||
mPreference.setAddWidgetEnabled(!mChangeListener.isAirplaneModeOn());
|
||||
mPreference.setOnAddClickListener(p -> startAddSimFlow());
|
||||
}
|
||||
|
||||
if (subs.size() == 1) {
|
||||
mPreference.setOnPreferenceClickListener((Preference pref) -> {
|
||||
final Intent intent = new Intent(mContext, MobileNetworkActivity.class);
|
||||
mContext.startActivity(intent);
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
mPreference.setFragment(MobileNetworkListFragment.class.getCanonicalName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -318,7 +318,8 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
// Try to get the network registration states
|
||||
ServiceState ss = mTelephonyManager.getServiceState();
|
||||
List<NetworkRegistrationState> networkList =
|
||||
ss.getNetworkRegistrationStates(AccessNetworkConstants.TransportType.WWAN);
|
||||
ss.getNetworkRegistrationStatesForTransportType(
|
||||
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
|
||||
if (networkList == null || networkList.size() == 0) {
|
||||
// Remove the connected network operators category
|
||||
mConnectedPreferenceCategory.setVisible(false);
|
||||
|
||||
@@ -152,6 +152,10 @@ public class AppNotificationSettings extends NotificationSettingsBase {
|
||||
context, mImportanceListener, mBackend));
|
||||
mControllers.add(new ImportancePreferenceController(
|
||||
context, mImportanceListener, mBackend));
|
||||
mControllers.add(new MinImportancePreferenceController(
|
||||
context, mImportanceListener, mBackend));
|
||||
mControllers.add(new HighImportancePreferenceController(
|
||||
context, mImportanceListener, mBackend));
|
||||
mControllers.add(new SoundPreferenceController(context, this,
|
||||
mImportanceListener, mBackend));
|
||||
mControllers.add(new LightsPreferenceController(context, mBackend));
|
||||
|
||||
@@ -30,7 +30,7 @@ public class BubblePreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String TAG = "BubblePrefContr";
|
||||
private static final String KEY = "bubble";
|
||||
private static final String KEY = "bubble_pref";
|
||||
private static final int SYSTEM_WIDE_ON = 1;
|
||||
private static final int SYSTEM_WIDE_OFF = 0;
|
||||
|
||||
|
||||
@@ -94,9 +94,12 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
mControllers = new ArrayList<>();
|
||||
mControllers.add(new HeaderPreferenceController(context, this));
|
||||
mControllers.add(new BlockPreferenceController(context, mImportanceListener, mBackend));
|
||||
mControllers.add(new ImportancePreferenceController(
|
||||
context, mImportanceListener, mBackend));
|
||||
mControllers.add(new MinImportancePreferenceController(
|
||||
context, mImportanceListener, mBackend));
|
||||
mControllers.add(new HighImportancePreferenceController(
|
||||
context, mImportanceListener, mBackend));
|
||||
mControllers.add(new AllowSoundPreferenceController(
|
||||
context, mImportanceListener, mBackend));
|
||||
mControllers.add(new SoundPreferenceController(context, this,
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
import static android.app.NotificationManager.IMPORTANCE_HIGH;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
public class HighImportancePreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String KEY_IMPORTANCE = "high_importance";
|
||||
private NotificationSettingsBase.ImportanceListener mImportanceListener;
|
||||
|
||||
public HighImportancePreferenceController(Context context,
|
||||
NotificationSettingsBase.ImportanceListener importanceListener,
|
||||
NotificationBackend backend) {
|
||||
super(context, backend);
|
||||
mImportanceListener = importanceListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_IMPORTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel == null) {
|
||||
return false;
|
||||
}
|
||||
if (isDefaultChannel()) {
|
||||
return false;
|
||||
}
|
||||
return mChannel.getImportance() >= IMPORTANCE_DEFAULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
if (mAppRow!= null && mChannel != null) {
|
||||
preference.setEnabled(mAdmin == null && isChannelConfigurable());
|
||||
|
||||
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
|
||||
pref.setChecked(mChannel.getImportance() >= IMPORTANCE_HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (mChannel != null) {
|
||||
final boolean checked = (boolean) newValue;
|
||||
|
||||
mChannel.setImportance(checked ? IMPORTANCE_HIGH : IMPORTANCE_DEFAULT);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
|
||||
saveChannel();
|
||||
mImportanceListener.onImportanceChanged();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
172
src/com/android/settings/notification/ImportancePreference.java
Normal file
172
src/com/android/settings/notification/ImportancePreference.java
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
import static android.app.NotificationManager.IMPORTANCE_HIGH;
|
||||
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||
import static android.app.NotificationManager.IMPORTANCE_MIN;
|
||||
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
public class ImportancePreference extends Preference {
|
||||
|
||||
boolean mIsBlockable = true;
|
||||
boolean mIsConfigurable = true;
|
||||
int mImportance;
|
||||
ImageButton blockButton;
|
||||
ImageButton silenceButton;
|
||||
ImageButton alertButton;
|
||||
ArrayMap<ImageButton, Integer> mImageButtons = new ArrayMap<>();
|
||||
Context mContext;
|
||||
|
||||
public ImportancePreference(Context context, AttributeSet attrs,
|
||||
int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public ImportancePreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public ImportancePreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public ImportancePreference(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
mContext = context;
|
||||
setLayoutResource(R.layout.notif_importance_preference);
|
||||
}
|
||||
|
||||
public void setImportance(int importance) {
|
||||
mImportance = importance;
|
||||
}
|
||||
|
||||
public void setBlockable(boolean blockable) {
|
||||
mIsBlockable = blockable;
|
||||
}
|
||||
|
||||
public void setConfigurable(boolean configurable) {
|
||||
mIsConfigurable = configurable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
|
||||
View blockView = holder.itemView.findViewById(R.id.block);
|
||||
View alertView = holder.itemView.findViewById(R.id.alert);
|
||||
View silenceView = holder.itemView.findViewById(R.id.silence);
|
||||
if (!mIsBlockable) {
|
||||
blockView.setVisibility(View.GONE);
|
||||
if (mImportance == IMPORTANCE_NONE) {
|
||||
mImportance = IMPORTANCE_LOW;
|
||||
callChangeListener(IMPORTANCE_LOW);
|
||||
}
|
||||
|
||||
}
|
||||
blockButton = blockView.findViewById(R.id.block_icon);
|
||||
silenceButton = silenceView.findViewById(R.id.silence_icon);
|
||||
alertButton = alertView.findViewById(R.id.alert_icon);
|
||||
mImageButtons.put(blockButton, mContext.getColor(R.color.notification_block_color));
|
||||
mImageButtons.put(silenceButton, mContext.getColor(R.color.notification_silence_color));
|
||||
mImageButtons.put(alertButton, mContext.getColor(R.color.notification_alert_color));
|
||||
|
||||
switch (mImportance) {
|
||||
case IMPORTANCE_NONE:
|
||||
colorizeImageButton(blockButton.getId());
|
||||
if (!mIsConfigurable) {
|
||||
alertView.setVisibility(View.GONE);
|
||||
silenceView.setVisibility(View.GONE);
|
||||
}
|
||||
break;
|
||||
case IMPORTANCE_MIN:
|
||||
case IMPORTANCE_LOW:
|
||||
colorizeImageButton(silenceButton.getId());
|
||||
if (!mIsConfigurable) {
|
||||
alertView.setVisibility(View.GONE);
|
||||
blockView.setVisibility(View.GONE);
|
||||
}
|
||||
break;
|
||||
case IMPORTANCE_HIGH:
|
||||
default:
|
||||
colorizeImageButton(alertButton.getId());
|
||||
if (!mIsConfigurable) {
|
||||
blockView.setVisibility(View.GONE);
|
||||
silenceView.setVisibility(View.GONE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
blockButton.setOnClickListener(v -> {
|
||||
callChangeListener(IMPORTANCE_NONE);
|
||||
colorizeImageButton(blockButton.getId());
|
||||
});
|
||||
silenceButton.setOnClickListener(v -> {
|
||||
callChangeListener(IMPORTANCE_LOW);
|
||||
colorizeImageButton(silenceButton.getId());
|
||||
});
|
||||
alertButton.setOnClickListener(v -> {
|
||||
callChangeListener(IMPORTANCE_DEFAULT);
|
||||
colorizeImageButton(alertButton.getId());
|
||||
});
|
||||
}
|
||||
|
||||
private void colorizeImageButton(int buttonId) {
|
||||
if (mImageButtons != null) {
|
||||
for (int i = 0; i < mImageButtons.size(); i++) {
|
||||
final ImageButton imageButton = mImageButtons.keyAt(i);
|
||||
final int color = mImageButtons.valueAt(i);
|
||||
if (imageButton != null) {
|
||||
LayerDrawable drawable = (LayerDrawable) imageButton.getDrawable();
|
||||
Drawable foreground = drawable.findDrawableByLayerId(R.id.fore);
|
||||
GradientDrawable background =
|
||||
(GradientDrawable) drawable.findDrawableByLayerId(R.id.back);
|
||||
if (buttonId == imageButton.getId()) {
|
||||
foreground.setTint(Color.WHITE);
|
||||
background.setColor(color);
|
||||
} else {
|
||||
foreground.setTint(color);
|
||||
background.setColor(Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,21 +18,15 @@ package com.android.settings.notification;
|
||||
|
||||
import static android.app.NotificationChannel.USER_LOCKED_SOUND;
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
import static android.app.NotificationManager.IMPORTANCE_HIGH;
|
||||
import static android.app.NotificationManager.IMPORTANCE_MIN;
|
||||
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.media.RingtoneManager;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.RestrictedListPreference;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
public class ImportancePreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
|
||||
|
||||
@@ -53,44 +47,33 @@ public class ImportancePreferenceController extends NotificationPreferenceContro
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
if (mAppRow == null) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel == null) {
|
||||
return false;
|
||||
}
|
||||
return !isDefaultChannel();
|
||||
if (isDefaultChannel()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
if (mAppRow!= null && mChannel != null) {
|
||||
preference.setEnabled(mAdmin == null && isChannelConfigurable());
|
||||
preference.setSummary(getImportanceSummary(mChannel));
|
||||
|
||||
int importances = IMPORTANCE_HIGH - IMPORTANCE_MIN + 1;
|
||||
CharSequence[] entries = new CharSequence[importances];
|
||||
CharSequence[] values = new CharSequence[importances];
|
||||
|
||||
int index = 0;
|
||||
for (int i = IMPORTANCE_HIGH; i >= IMPORTANCE_MIN; i--) {
|
||||
NotificationChannel channel = new NotificationChannel("", "", i);
|
||||
entries[index] = getImportanceSummary(channel);
|
||||
values[index] = String.valueOf(i);
|
||||
index++;
|
||||
}
|
||||
|
||||
RestrictedListPreference pref = (RestrictedListPreference) preference;
|
||||
pref.setEntries(entries);
|
||||
pref.setEntryValues(values);
|
||||
pref.setValue(String.valueOf(mChannel.getImportance()));
|
||||
ImportancePreference pref = (ImportancePreference) preference;
|
||||
pref.setBlockable(isChannelBlockable());
|
||||
pref.setConfigurable(isChannelConfigurable());
|
||||
pref.setImportance(mChannel.getImportance());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (mChannel != null) {
|
||||
final int importance = Integer.parseInt((String) newValue);
|
||||
final int importance = (Integer) newValue;
|
||||
|
||||
// If you are moving from an importance level without sound to one with sound,
|
||||
// but the sound you had selected was "Silence",
|
||||
@@ -111,39 +94,4 @@ public class ImportancePreferenceController extends NotificationPreferenceContro
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected String getImportanceSummary(NotificationChannel channel) {
|
||||
String summary = "";
|
||||
int importance = channel.getImportance();
|
||||
switch (importance) {
|
||||
case IMPORTANCE_UNSPECIFIED:
|
||||
summary = mContext.getString(R.string.notification_importance_unspecified);
|
||||
break;
|
||||
case NotificationManager.IMPORTANCE_MIN:
|
||||
summary = mContext.getString(R.string.notification_importance_min);
|
||||
break;
|
||||
case NotificationManager.IMPORTANCE_LOW:
|
||||
summary = mContext.getString(R.string.notification_importance_low);
|
||||
break;
|
||||
case NotificationManager.IMPORTANCE_DEFAULT:
|
||||
if (SoundPreferenceController.hasValidSound(channel)) {
|
||||
summary = mContext.getString(R.string.notification_importance_default);
|
||||
} else {
|
||||
summary = mContext.getString(R.string.notification_importance_low);
|
||||
}
|
||||
break;
|
||||
case NotificationManager.IMPORTANCE_HIGH:
|
||||
case NotificationManager.IMPORTANCE_MAX:
|
||||
if (SoundPreferenceController.hasValidSound(channel)) {
|
||||
summary = mContext.getString(R.string.notification_importance_high);
|
||||
} else {
|
||||
summary = mContext.getString(R.string.notification_importance_high_silent);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
return summary;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||
import static android.app.NotificationManager.IMPORTANCE_MIN;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
public class MinImportancePreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String KEY_IMPORTANCE = "min_importance";
|
||||
private NotificationSettingsBase.ImportanceListener mImportanceListener;
|
||||
|
||||
public MinImportancePreferenceController(Context context,
|
||||
NotificationSettingsBase.ImportanceListener importanceListener,
|
||||
NotificationBackend backend) {
|
||||
super(context, backend);
|
||||
mImportanceListener = importanceListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_IMPORTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel == null) {
|
||||
return false;
|
||||
}
|
||||
if (isDefaultChannel()) {
|
||||
return false;
|
||||
}
|
||||
return mChannel.getImportance() <= IMPORTANCE_LOW;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
if (mAppRow!= null && mChannel != null) {
|
||||
preference.setEnabled(mAdmin == null && isChannelConfigurable());
|
||||
|
||||
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
|
||||
pref.setChecked(mChannel.getImportance() == IMPORTANCE_MIN);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (mChannel != null) {
|
||||
final boolean checked = (boolean) newValue;
|
||||
|
||||
mChannel.setImportance(checked ? IMPORTANCE_MIN : IMPORTANCE_LOW);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
|
||||
saveChannel();
|
||||
mImportanceListener.onImportanceChanged();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -111,6 +111,9 @@ public abstract class NotificationPreferenceController extends AbstractPreferenc
|
||||
}
|
||||
|
||||
protected boolean isChannelConfigurable() {
|
||||
if (mAppRow != null && mAppRow.lockedImportance) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel != null && mAppRow != null) {
|
||||
return !Objects.equals(mChannel.getId(), mAppRow.lockedChannelId);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.android.settingslib.volume.MediaSessions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class RemoteVolumePreferenceController extends
|
||||
VolumeSeekBarPreferenceController {
|
||||
@@ -58,14 +59,14 @@ public class RemoteVolumePreferenceController extends
|
||||
if (mActiveToken == null) {
|
||||
updateToken(token);
|
||||
}
|
||||
if (mActiveToken == token) {
|
||||
if (Objects.equals(mActiveToken, token)) {
|
||||
updatePreference(mPreference, mActiveToken, pi);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoteRemoved(MediaSession.Token t) {
|
||||
if (mActiveToken == t) {
|
||||
if (Objects.equals(mActiveToken, t)) {
|
||||
updateToken(null);
|
||||
if (mPreference != null) {
|
||||
mPreference.setVisible(false);
|
||||
@@ -75,7 +76,7 @@ public class RemoteVolumePreferenceController extends
|
||||
|
||||
@Override
|
||||
public void onRemoteVolumeChanged(MediaSession.Token token, int flags) {
|
||||
if (mActiveToken == token) {
|
||||
if (Objects.equals(mActiveToken, token)) {
|
||||
final MediaController.PlaybackInfo pi = mMediaController.getPlaybackInfo();
|
||||
if (pi != null) {
|
||||
setSliderPosition(pi.getCurrentVolume());
|
||||
@@ -116,13 +117,13 @@ public class RemoteVolumePreferenceController extends
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
//TODO(b/126199571): register callback once b/126890783 is fixed
|
||||
mMediaSessions.init();
|
||||
}
|
||||
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
//TODO(b/126199571): unregister callback once b/126890783 is fixed
|
||||
mMediaSessions.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -189,8 +190,7 @@ public class RemoteVolumePreferenceController extends
|
||||
|
||||
@Override
|
||||
public Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
|
||||
//TODO(b/126199571): return RemoteVolumeSliceWorker once b/126890783 is fixed
|
||||
return null;
|
||||
return RemoteVolumeSliceWorker.class;
|
||||
}
|
||||
|
||||
private void updatePreference(VolumeSeekBarPreference seekBarPreference,
|
||||
|
||||
@@ -171,6 +171,9 @@ public class ZenRulePreference extends TwoTargetPreference {
|
||||
getSettingsActivity(rule, si);
|
||||
mIntent = AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action,
|
||||
settingsActivity, mId);
|
||||
if (mIntent.resolveActivity(mPm) == null) {
|
||||
mIntent = null;
|
||||
}
|
||||
setKey(mId);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,7 @@ public class PanelSlicesAdapter
|
||||
super(view);
|
||||
sliceView = view.findViewById(R.id.slice_view);
|
||||
sliceView.setMode(SliceView.MODE_LARGE);
|
||||
sliceView.showTitleItems(true);
|
||||
mPanelContent = panelContent;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.slices;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* Manages custom {@link androidx.slice.Slice Slices}, which are all Slices not backed by
|
||||
* preferences.
|
||||
*/
|
||||
public class CustomSliceManager {
|
||||
|
||||
private final Context mContext;
|
||||
private final Map<Uri, CustomSliceable> mSliceableCache;
|
||||
|
||||
public CustomSliceManager(Context context) {
|
||||
mContext = context.getApplicationContext();
|
||||
mSliceableCache = new WeakHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link CustomSliceable} associated to the Uri.
|
||||
* <p>
|
||||
* Do not change this method signature to accommodate for a special-case slicable - a context is
|
||||
* the only thing that should be needed to create the object.
|
||||
*/
|
||||
public CustomSliceable getSliceableFromUri(Uri uri) {
|
||||
final Uri newUri = CustomSliceRegistry.removeParameterFromUri(uri);
|
||||
if (mSliceableCache.containsKey(newUri)) {
|
||||
return mSliceableCache.get(newUri);
|
||||
}
|
||||
|
||||
final Class clazz = CustomSliceRegistry.getSliceClassByUri(newUri);
|
||||
if (clazz == null) {
|
||||
throw new IllegalArgumentException("No Slice found for uri: " + uri);
|
||||
}
|
||||
|
||||
final CustomSliceable sliceable = CustomSliceable.createInstance(mContext, clazz);
|
||||
mSliceableCache.put(newUri, sliceable);
|
||||
return sliceable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a {@link CustomSliceable} associated to the Action.
|
||||
* <p>
|
||||
* Do not change this method signature to accommodate for a special-case sliceable - a context
|
||||
* is the only thing that should be needed to create the object.
|
||||
*/
|
||||
public CustomSliceable getSliceableFromIntentAction(String action) {
|
||||
return getSliceableFromUri(Uri.parse(action));
|
||||
}
|
||||
}
|
||||
@@ -322,7 +322,7 @@ public class CustomSliceRegistry {
|
||||
}
|
||||
|
||||
public static Class<? extends CustomSliceable> getSliceClassByUri(Uri uri) {
|
||||
return sUriToSlice.get(uri);
|
||||
return sUriToSlice.get(removeParameterFromUri(uri));
|
||||
}
|
||||
|
||||
public static Uri removeParameterFromUri(Uri uri) {
|
||||
@@ -331,7 +331,7 @@ public class CustomSliceRegistry {
|
||||
|
||||
/**
|
||||
* Returns {@code true} if {@param uri} is a valid Slice Uri handled by
|
||||
* {@link CustomSliceManager}.
|
||||
* {@link CustomSliceRegistry}.
|
||||
*/
|
||||
public static boolean isValidUri(Uri uri) {
|
||||
return sUriToSlice.containsKey(removeParameterFromUri(uri));
|
||||
@@ -339,7 +339,7 @@ public class CustomSliceRegistry {
|
||||
|
||||
/**
|
||||
* Returns {@code true} if {@param action} is a valid intent action handled by
|
||||
* {@link CustomSliceManager}.
|
||||
* {@link CustomSliceRegistry}.
|
||||
*/
|
||||
public static boolean isValidAction(String action) {
|
||||
return isValidUri(Uri.parse(action));
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.android.settings.slices;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.slice.Slice;
|
||||
@@ -106,16 +105,17 @@ public interface CustomSliceable extends Sliceable {
|
||||
/**
|
||||
* Build an instance of a {@link CustomSliceable} which has a {@link Context}-only constructor.
|
||||
*/
|
||||
static CustomSliceable createInstance(Context context, Class<CustomSliceable> sliceableClass) {
|
||||
static CustomSliceable createInstance(Context context,
|
||||
Class<? extends CustomSliceable> sliceable) {
|
||||
try {
|
||||
final Constructor<CustomSliceable> sliceable =
|
||||
sliceableClass.getConstructor(Context.class);
|
||||
final Object[] params = new Object[]{context};
|
||||
return sliceable.newInstance(params);
|
||||
final Constructor<? extends CustomSliceable> constructor =
|
||||
sliceable.getConstructor(Context.class);
|
||||
final Object[] params = new Object[]{context.getApplicationContext()};
|
||||
return constructor.newInstance(params);
|
||||
} catch (NoSuchMethodException | InstantiationException |
|
||||
IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
|
||||
throw new IllegalStateException(
|
||||
"Invalid sliceable class: " + sliceableClass, e);
|
||||
"Invalid sliceable class: " + sliceable, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,9 +117,6 @@ public class SettingsSliceProvider extends SliceProvider {
|
||||
|
||||
private static final KeyValueListParser KEY_VALUE_LIST_PARSER = new KeyValueListParser(',');
|
||||
|
||||
@VisibleForTesting
|
||||
CustomSliceManager mCustomSliceManager;
|
||||
|
||||
@VisibleForTesting
|
||||
SlicesDatabaseAccessor mSlicesDatabaseAccessor;
|
||||
|
||||
@@ -140,15 +137,15 @@ public class SettingsSliceProvider extends SliceProvider {
|
||||
mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(getContext());
|
||||
mSliceDataCache = new ConcurrentHashMap<>();
|
||||
mSliceWeakDataCache = new WeakHashMap<>();
|
||||
mCustomSliceManager = FeatureFactory.getFactory(
|
||||
getContext()).getSlicesFeatureProvider().getCustomSliceManager(getContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSlicePinned(Uri sliceUri) {
|
||||
if (CustomSliceRegistry.isValidUri(sliceUri)) {
|
||||
final CustomSliceable sliceable = mCustomSliceManager.getSliceableFromUri(sliceUri);
|
||||
final Context context = getContext();
|
||||
final CustomSliceable sliceable = FeatureFactory.getFactory(context)
|
||||
.getSlicesFeatureProvider().getSliceableFromUri(context, sliceUri);
|
||||
final IntentFilter filter = sliceable.getIntentFilter();
|
||||
if (filter != null) {
|
||||
registerIntentToUri(filter, sliceUri);
|
||||
@@ -195,9 +192,10 @@ public class SettingsSliceProvider extends SliceProvider {
|
||||
// Before adding a slice to {@link CustomSliceManager}, please get approval
|
||||
// from the Settings team.
|
||||
if (CustomSliceRegistry.isValidUri(sliceUri)) {
|
||||
final CustomSliceable sliceable = mCustomSliceManager.getSliceableFromUri(
|
||||
sliceUri);
|
||||
return sliceable.getSlice();
|
||||
final Context context = getContext();
|
||||
return FeatureFactory.getFactory(context)
|
||||
.getSlicesFeatureProvider().getSliceableFromUri(context, sliceUri)
|
||||
.getSlice();
|
||||
}
|
||||
|
||||
if (CustomSliceRegistry.WIFI_CALLING_URI.equals(sliceUri)) {
|
||||
|
||||
@@ -61,11 +61,10 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
|
||||
final boolean isPlatformSlice = intent.getBooleanExtra(EXTRA_SLICE_PLATFORM_DEFINED,
|
||||
false /* default */);
|
||||
|
||||
final CustomSliceManager mCustomSliceManager = FeatureFactory.getFactory(
|
||||
context).getSlicesFeatureProvider().getCustomSliceManager(context);
|
||||
if (CustomSliceRegistry.isValidAction(action)) {
|
||||
final CustomSliceable sliceable =
|
||||
mCustomSliceManager.getSliceableFromIntentAction(action);
|
||||
CustomSliceable.createInstance(context,
|
||||
CustomSliceRegistry.getSliceClassByUri(Uri.parse(action)));
|
||||
sliceable.onNotifyChange(intent);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.util.Log;
|
||||
|
||||
import com.android.settings.bluetooth.BluetoothSliceBuilder;
|
||||
import com.android.settings.notification.ZenModeSliceBuilder;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
|
||||
public class SliceDeepLinkSpringBoard extends Activity {
|
||||
|
||||
@@ -45,11 +44,10 @@ public class SliceDeepLinkSpringBoard extends Activity {
|
||||
Intent launchIntent;
|
||||
|
||||
// TODO (b/80263568) Avoid duplicating this list of Slice Uris.
|
||||
final CustomSliceManager customSliceManager = FeatureFactory.getFactory(this)
|
||||
.getSlicesFeatureProvider().getCustomSliceManager(this);
|
||||
if (CustomSliceRegistry.isValidUri(sliceUri)) {
|
||||
final CustomSliceable sliceable =
|
||||
customSliceManager.getSliceableFromUri(sliceUri);
|
||||
CustomSliceable.createInstance(getApplicationContext(),
|
||||
CustomSliceRegistry.getSliceClassByUri(sliceUri));
|
||||
launchIntent = sliceable.getIntent();
|
||||
} else if (CustomSliceRegistry.ZEN_MODE_SLICE_URI.equals(sliceUri)) {
|
||||
launchIntent = ZenModeSliceBuilder.getIntent(this /* context */);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.android.settings.slices;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.android.settings.network.telephony.Enhanced4gLteSliceHelper;
|
||||
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
|
||||
@@ -12,10 +13,22 @@ public interface SlicesFeatureProvider {
|
||||
|
||||
boolean DEBUG = false;
|
||||
|
||||
SlicesIndexer getSliceIndexer(Context context);
|
||||
|
||||
SliceDataConverter getSliceDataConverter(Context context);
|
||||
|
||||
/**
|
||||
* Starts a new UI session for the purpose of using Slices.
|
||||
*
|
||||
* A UI session is defined as an duration of time when user stays in a UI screen. Screen
|
||||
* rotation does not break the continuation of session, going to a sub-page and coming out does
|
||||
* not break the continuation either. Leaving the page and coming back breaks it.
|
||||
*/
|
||||
void newUiSession();
|
||||
|
||||
/**
|
||||
* Returns the token created in {@link #newUiSession}.
|
||||
*/
|
||||
long getUiSessionToken();
|
||||
|
||||
/**
|
||||
* Asynchronous call to index the data used to build Slices.
|
||||
* If the data is already indexed, the data will not change.
|
||||
@@ -28,7 +41,14 @@ public interface SlicesFeatureProvider {
|
||||
*/
|
||||
void indexSliceData(Context context);
|
||||
|
||||
CustomSliceManager getCustomSliceManager(Context context);
|
||||
|
||||
/**
|
||||
* Return a {@link CustomSliceable} associated to the Uri.
|
||||
* <p>
|
||||
* Do not change this method signature to accommodate for a special-case sliceable - a context
|
||||
* is the only thing that should be needed to create the object.
|
||||
*/
|
||||
CustomSliceable getSliceableFromUri(Context context, Uri uri);
|
||||
|
||||
/**
|
||||
* Gets new WifiCallingSliceHelper object
|
||||
|
||||
@@ -17,27 +17,23 @@
|
||||
package com.android.settings.slices;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import com.android.settings.network.telephony.Enhanced4gLteSliceHelper;
|
||||
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Manages Slices in Settings.
|
||||
*/
|
||||
public class SlicesFeatureProviderImpl implements SlicesFeatureProvider {
|
||||
|
||||
private long mUiSessionToken;
|
||||
private SlicesIndexer mSlicesIndexer;
|
||||
private SliceDataConverter mSliceDataConverter;
|
||||
private CustomSliceManager mCustomSliceManager;
|
||||
|
||||
@Override
|
||||
public SlicesIndexer getSliceIndexer(Context context) {
|
||||
if (mSlicesIndexer == null) {
|
||||
mSlicesIndexer = new SlicesIndexer(context.getApplicationContext());
|
||||
}
|
||||
return mSlicesIndexer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SliceDataConverter getSliceDataConverter(Context context) {
|
||||
@@ -48,11 +44,13 @@ public class SlicesFeatureProviderImpl implements SlicesFeatureProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomSliceManager getCustomSliceManager(Context context) {
|
||||
if (mCustomSliceManager == null) {
|
||||
mCustomSliceManager = new CustomSliceManager(context.getApplicationContext());
|
||||
}
|
||||
return mCustomSliceManager;
|
||||
public void newUiSession() {
|
||||
mUiSessionToken = SystemClock.elapsedRealtime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUiSessionToken() {
|
||||
return mUiSessionToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,4 +74,23 @@ public class SlicesFeatureProviderImpl implements SlicesFeatureProvider {
|
||||
public Enhanced4gLteSliceHelper getNewEnhanced4gLteSliceHelper(Context context) {
|
||||
return new Enhanced4gLteSliceHelper(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomSliceable getSliceableFromUri(Context context, Uri uri) {
|
||||
final Uri newUri = CustomSliceRegistry.removeParameterFromUri(uri);
|
||||
final Class clazz = CustomSliceRegistry.getSliceClassByUri(newUri);
|
||||
if (clazz == null) {
|
||||
throw new IllegalArgumentException("No Slice found for uri: " + uri);
|
||||
}
|
||||
|
||||
final CustomSliceable sliceable = CustomSliceable.createInstance(context, clazz);
|
||||
return sliceable;
|
||||
}
|
||||
|
||||
private SlicesIndexer getSliceIndexer(Context context) {
|
||||
if (mSlicesIndexer == null) {
|
||||
mSlicesIndexer = new SlicesIndexer(context.getApplicationContext());
|
||||
}
|
||||
return mSlicesIndexer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ public class WifiConfigController implements TextWatcher,
|
||||
mHiddenSettingsSpinner = mView.findViewById(R.id.hidden_settings);
|
||||
mPrivacySettingsSpinner = mView.findViewById(R.id.privacy_settings);
|
||||
if (mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_wifi_p2p_mac_randomization_supported)) {
|
||||
com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported)) {
|
||||
View privacySettingsLayout = mView.findViewById(R.id.privacy_settings_fields);
|
||||
privacySettingsLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ import com.android.settings.widget.SummaryUpdater.OnSummaryChangeListener;
|
||||
import com.android.settings.widget.SwitchBarController;
|
||||
import com.android.settings.wifi.details.WifiNetworkDetailsFragment;
|
||||
import com.android.settings.wifi.dpp.WifiDppUtils;
|
||||
import com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
@@ -968,8 +969,13 @@ public class WifiSettings extends RestrictedSettingsFragment
|
||||
}
|
||||
|
||||
private void launchNetworkDetailsFragment(ConnectedAccessPointPreference pref) {
|
||||
final AccessPoint accessPoint = pref.getAccessPoint();
|
||||
final Context context = getContext();
|
||||
final CharSequence title = SavedAccessPointsWifiSettings.usingDetailsFragment(context) ?
|
||||
accessPoint.getTitle() : context.getText(R.string.pref_title_network_details);
|
||||
|
||||
new SubSettingLauncher(getContext())
|
||||
.setTitleRes(R.string.pref_title_network_details)
|
||||
.setTitleText(title)
|
||||
.setDestination(WifiNetworkDetailsFragment.class.getName())
|
||||
.setArguments(pref.getExtras())
|
||||
.setSourceMetricsCategory(getMetricsCategory())
|
||||
|
||||
137
src/com/android/settings/wifi/calling/DisclaimerItem.java
Normal file
137
src/com/android/settings/wifi/calling/DisclaimerItem.java
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi.calling;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.PersistableBundle;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
/**
|
||||
* Interface to control disclaimer item from {@link WifiCallingDisclaimerFragment}.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public abstract class DisclaimerItem {
|
||||
private static final String SHARED_PREFERENCES_NAME = "wfc_disclaimer_prefs";
|
||||
|
||||
protected final Context mContext;
|
||||
protected final int mSubId;
|
||||
private final CarrierConfigManager mCarrierConfigManager;
|
||||
|
||||
DisclaimerItem(Context context, int subId) {
|
||||
mContext = context;
|
||||
mSubId = subId;
|
||||
mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the {@link WifiCallingDisclaimerFragment} when a user has clicked the agree button.
|
||||
*/
|
||||
void onAgreed() {
|
||||
setBooleanSharedPrefs(getPrefKey(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the disclaimer item need to be displayed or not.
|
||||
*
|
||||
* @return Returns {@code true} if disclaimer item need to be displayed,
|
||||
* {@code false} if not displayed.
|
||||
*/
|
||||
boolean shouldShow() {
|
||||
if (getBooleanSharedPrefs(getPrefKey(), false)) {
|
||||
logd("shouldShow: false due to a user has already agreed.");
|
||||
return false;
|
||||
}
|
||||
logd("shouldShow: true");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configuration values for a particular sub id.
|
||||
*
|
||||
* @return The {@link PersistableBundle} instance containing the config value for a
|
||||
* particular phone id, or default values.
|
||||
*/
|
||||
protected PersistableBundle getCarrierConfig() {
|
||||
PersistableBundle config = mCarrierConfigManager.getConfigForSubId(mSubId);
|
||||
if (config != null) {
|
||||
return config;
|
||||
}
|
||||
// Return static default defined in CarrierConfigManager.
|
||||
return CarrierConfigManager.getDefaultConfig();
|
||||
}
|
||||
|
||||
protected void logd(String msg) {
|
||||
Log.d(getName(), "[" + mSubId + "] " + msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a title id for disclaimer item.
|
||||
*
|
||||
* @return Title id for disclaimer item.
|
||||
*/
|
||||
protected abstract int getTitleId();
|
||||
|
||||
/**
|
||||
* Gets a message id for disclaimer item.
|
||||
*
|
||||
* @return Message id for disclaimer item.
|
||||
*/
|
||||
protected abstract int getMessageId();
|
||||
|
||||
/**
|
||||
* Gets a name of disclaimer item.
|
||||
*
|
||||
* @return Name of disclaimer item.
|
||||
*/
|
||||
protected abstract String getName();
|
||||
|
||||
/**
|
||||
* Gets a preference key to keep user's consent.
|
||||
*
|
||||
* @return Preference key to keep user's consent.
|
||||
*/
|
||||
protected abstract String getPrefKey();
|
||||
|
||||
/**
|
||||
* Gets the boolean value from shared preferences.
|
||||
*
|
||||
* @param key The key for the preference item.
|
||||
* @param defValue Value to return if this preference does not exist.
|
||||
* @return The boolean value of corresponding key, or defValue.
|
||||
*/
|
||||
private boolean getBooleanSharedPrefs(String key, boolean defValue) {
|
||||
SharedPreferences prefs = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME,
|
||||
Context.MODE_PRIVATE);
|
||||
return prefs.getBoolean(key + mSubId, defValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the boolean value to shared preferences.
|
||||
*
|
||||
* @param key The key for the preference item.
|
||||
* @param value The value to be set for shared preferences.
|
||||
*/
|
||||
private void setBooleanSharedPrefs(String key, boolean value) {
|
||||
SharedPreferences prefs = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME,
|
||||
Context.MODE_PRIVATE);
|
||||
prefs.edit().putBoolean(key + mSubId, value).apply();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi.calling;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Factory class to create disclaimer items list.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public final class DisclaimerItemFactory {
|
||||
|
||||
/**
|
||||
* Creates disclaimer items list.
|
||||
*
|
||||
* @param context The application context
|
||||
* @param subId The subscription id.
|
||||
* @return The {@link DisclaimerItem} list instance, if there are no items, return empty list.
|
||||
*/
|
||||
public static List<DisclaimerItem> create(Context context, int subId) {
|
||||
List<DisclaimerItem> itemList = getDisclaimerItemList(context, subId);
|
||||
Iterator itr = itemList.iterator();
|
||||
while (itr.hasNext()) {
|
||||
DisclaimerItem item = (DisclaimerItem) itr.next();
|
||||
if (!item.shouldShow()) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
return itemList;
|
||||
}
|
||||
|
||||
private static List<DisclaimerItem> getDisclaimerItemList(Context context, int subId) {
|
||||
List<DisclaimerItem> itemList = new ArrayList<DisclaimerItem>();
|
||||
|
||||
return itemList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi.calling;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Adapter for disclaimer items list.
|
||||
*/
|
||||
public class DisclaimerItemListAdapter extends
|
||||
RecyclerView.Adapter<DisclaimerItemListAdapter.DisclaimerItemViewHolder> {
|
||||
|
||||
private List<DisclaimerItem> mDisclaimerItemList;
|
||||
|
||||
public DisclaimerItemListAdapter(List<DisclaimerItem> list) {
|
||||
mDisclaimerItemList = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisclaimerItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(
|
||||
Context.LAYOUT_INFLATER_SERVICE);
|
||||
View view = inflater.inflate(R.layout.wfc_simple_disclaimer_item, null, false);
|
||||
return new DisclaimerItemViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(DisclaimerItemViewHolder holder, int position) {
|
||||
holder.titleView.setText(mDisclaimerItemList.get(position).getTitleId());
|
||||
holder.descriptionView.setText(mDisclaimerItemList.get(position).getMessageId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mDisclaimerItemList.size();
|
||||
}
|
||||
|
||||
public static class DisclaimerItemViewHolder extends RecyclerView.ViewHolder {
|
||||
@VisibleForTesting
|
||||
static final int ID_DISCLAIMER_ITEM_TITLE = R.id.disclaimer_title;
|
||||
@VisibleForTesting
|
||||
static final int ID_DISCLAIMER_ITEM_DESCRIPTION = R.id.disclaimer_desc;
|
||||
|
||||
public final TextView titleView;
|
||||
public final TextView descriptionView;
|
||||
|
||||
public DisclaimerItemViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
titleView = itemView.findViewById(ID_DISCLAIMER_ITEM_TITLE);
|
||||
descriptionView = itemView.findViewById(ID_DISCLAIMER_ITEM_DESCRIPTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi.calling;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.InstrumentedFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Fragment for displaying disclaimers for WFC.
|
||||
*/
|
||||
public class WifiCallingDisclaimerFragment extends InstrumentedFragment
|
||||
implements View.OnClickListener {
|
||||
private static final String TAG = "WifiCallingDisclaimerFragment";
|
||||
|
||||
private static final String STATE_IS_SCROLL_TO_BOTTOM = "state_is_scroll_to_bottom";
|
||||
|
||||
private List<DisclaimerItem> mDisclaimerItemList = new ArrayList<DisclaimerItem>();
|
||||
private Button mAgreeButton;
|
||||
private Button mDisagreeButton;
|
||||
private boolean mScrollToBottom;
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.WIFI_CALLING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final Bundle args = getArguments();
|
||||
final int subId = (args != null) ? args.getInt(WifiCallingSettingsForSub.EXTRA_SUB_ID)
|
||||
: SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
|
||||
|
||||
mDisclaimerItemList = DisclaimerItemFactory.create(getActivity(), subId);
|
||||
if (mDisclaimerItemList.isEmpty()) {
|
||||
finish(Activity.RESULT_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mScrollToBottom = savedInstanceState.getBoolean(
|
||||
STATE_IS_SCROLL_TO_BOTTOM, mScrollToBottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
final View view = inflater.inflate(R.layout.wfc_disclaimer_fragment, container, false);
|
||||
|
||||
mAgreeButton = view.findViewById(R.id.agree_button);
|
||||
mAgreeButton.setOnClickListener(this);
|
||||
mDisagreeButton = view.findViewById(R.id.disagree_button);
|
||||
mDisagreeButton.setOnClickListener(this);
|
||||
|
||||
final RecyclerView recyclerView = (RecyclerView) view.findViewById(
|
||||
R.id.disclaimer_item_list);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||
recyclerView.setAdapter(new DisclaimerItemListAdapter(mDisclaimerItemList));
|
||||
|
||||
RecyclerView.ItemDecoration itemDecoration =
|
||||
new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL);
|
||||
recyclerView.addItemDecoration(itemDecoration);
|
||||
|
||||
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
if (!recyclerView.canScrollVertically(1 /* scrolling down */)) {
|
||||
mScrollToBottom = true;
|
||||
updateButtonState();
|
||||
recyclerView.removeOnScrollListener(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
updateButtonState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(STATE_IS_SCROLL_TO_BOTTOM, mScrollToBottom);
|
||||
}
|
||||
|
||||
private void updateButtonState() {
|
||||
mAgreeButton.setEnabled(mScrollToBottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == mAgreeButton) {
|
||||
for (DisclaimerItem item : mDisclaimerItemList) {
|
||||
item.onAgreed();
|
||||
}
|
||||
finish(Activity.RESULT_OK);
|
||||
} else if (v == mDisagreeButton) {
|
||||
finish(Activity.RESULT_CANCELED);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void finish(int result) {
|
||||
Activity activity = getActivity();
|
||||
activity.setResult(result, null);
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
|
||||
/**
|
||||
@@ -69,9 +70,13 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
||||
private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
|
||||
private static final String PREFERENCE_EMERGENCY_ADDRESS = "emergency_address_key";
|
||||
|
||||
private static final int REQUEST_CHECK_WFC_EMERGENCY_ADDRESS = 1;
|
||||
@VisibleForTesting
|
||||
static final int REQUEST_CHECK_WFC_EMERGENCY_ADDRESS = 1;
|
||||
@VisibleForTesting
|
||||
static final int REQUEST_CHECK_WFC_DISCLAIMER = 2;
|
||||
|
||||
public static final String EXTRA_LAUNCH_CARRIER_APP = "EXTRA_LAUNCH_CARRIER_APP";
|
||||
public static final String EXTRA_SUB_ID = "EXTRA_SUB_ID";
|
||||
|
||||
protected static final String FRAGMENT_BUNDLE_SUBID = "subId";
|
||||
|
||||
@@ -172,7 +177,7 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
||||
|
||||
mEmptyView = getView().findViewById(android.R.id.empty);
|
||||
setEmptyView(mEmptyView);
|
||||
final Resources res = SubscriptionManager.getResourcesForSubId(getContext(), mSubId);
|
||||
final Resources res = getResourcesForSubId();
|
||||
String emptyViewText = res.getString(R.string.wifi_calling_off_explanation,
|
||||
res.getString(R.string.wifi_calling_off_explanation_2));
|
||||
mEmptyView.setText(emptyViewText);
|
||||
@@ -416,14 +421,17 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
||||
return;
|
||||
}
|
||||
|
||||
// Call address management activity before turning on WFC
|
||||
Intent carrierAppIntent = getCarrierActivityIntent();
|
||||
if (carrierAppIntent != null) {
|
||||
carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_ACTIVATE);
|
||||
startActivityForResult(carrierAppIntent, REQUEST_CHECK_WFC_EMERGENCY_ADDRESS);
|
||||
} else {
|
||||
updateWfcMode(true);
|
||||
}
|
||||
// Launch disclaimer fragment before turning on WFC
|
||||
final Context context = getActivity();
|
||||
final Bundle args = new Bundle();
|
||||
args.putInt(EXTRA_SUB_ID, mSubId);
|
||||
new SubSettingLauncher(context)
|
||||
.setDestination(WifiCallingDisclaimerFragment.class.getName())
|
||||
.setArguments(args)
|
||||
.setTitleRes(R.string.wifi_calling_settings_title)
|
||||
.setSourceMetricsCategory(getMetricsCategory())
|
||||
.setResultListener(this, REQUEST_CHECK_WFC_DISCLAIMER)
|
||||
.launch();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -476,12 +484,30 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
||||
|
||||
final Context context = getActivity();
|
||||
|
||||
if (requestCode == REQUEST_CHECK_WFC_EMERGENCY_ADDRESS) {
|
||||
Log.d(TAG, "WFC emergency address activity result = " + resultCode);
|
||||
Log.d(TAG, "WFC activity request = " + requestCode + " result = " + resultCode);
|
||||
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
updateWfcMode(true);
|
||||
}
|
||||
switch (requestCode) {
|
||||
case REQUEST_CHECK_WFC_EMERGENCY_ADDRESS:
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
updateWfcMode(true);
|
||||
}
|
||||
break;
|
||||
case REQUEST_CHECK_WFC_DISCLAIMER:
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
// Call address management activity before turning on WFC
|
||||
Intent carrierAppIntent = getCarrierActivityIntent();
|
||||
if (carrierAppIntent != null) {
|
||||
carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_ACTIVATE);
|
||||
startActivityForResult(carrierAppIntent,
|
||||
REQUEST_CHECK_WFC_EMERGENCY_ADDRESS);
|
||||
} else {
|
||||
updateWfcMode(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Unexpected request: " + requestCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -568,4 +594,9 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
||||
}
|
||||
return resId;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Resources getResourcesForSubId() {
|
||||
return SubscriptionManager.getResourcesForSubId(getContext(), mSubId, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
import android.util.FeatureFlagUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
@@ -51,12 +52,14 @@ import androidx.core.text.BidiFormatter;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.FeatureFlags;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.datausage.WifiDataUsageSummaryPreferenceController;
|
||||
import com.android.settings.development.featureflags.FeatureFlagPersistent;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
import com.android.settings.wifi.WifiDialog;
|
||||
@@ -150,6 +153,9 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
private Preference mDnsPref;
|
||||
private PreferenceCategory mIpv6Category;
|
||||
private Preference mIpv6AddressPref;
|
||||
private Lifecycle mLifecycle;
|
||||
Preference mDataUsageSummaryPref;
|
||||
WifiDataUsageSummaryPreferenceController mSummaryHeaderController;
|
||||
|
||||
private final IconInjector mIconInjector;
|
||||
private final IntentFilter mFilter;
|
||||
@@ -262,6 +268,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
|
||||
mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
|
||||
|
||||
mLifecycle = lifecycle;
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
|
||||
@@ -313,6 +320,17 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
|
||||
private void setupEntityHeader(PreferenceScreen screen) {
|
||||
LayoutPreference headerPref = screen.findPreference(KEY_HEADER);
|
||||
|
||||
if (usingDataUsageHeader(mContext)) {
|
||||
headerPref.setVisible(false);
|
||||
mDataUsageSummaryPref = screen.findPreference("status_header");
|
||||
mDataUsageSummaryPref.setVisible(true);
|
||||
mSummaryHeaderController =
|
||||
new WifiDataUsageSummaryPreferenceController(mFragment.getActivity(),
|
||||
mLifecycle, (PreferenceFragmentCompat) mFragment, mAccessPoint.getSsid());
|
||||
return;
|
||||
}
|
||||
|
||||
mEntityHeaderController =
|
||||
EntityHeaderController.newInstance(
|
||||
mFragment.getActivity(), mFragment,
|
||||
@@ -326,6 +344,15 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
mEntityHeaderController.setLabel(mAccessPoint.getTitle());
|
||||
}
|
||||
|
||||
private void refreshEntityHeader() {
|
||||
if (usingDataUsageHeader(mContext)) {
|
||||
mSummaryHeaderController.updateState(mDataUsageSummaryPref);
|
||||
} else {
|
||||
mEntityHeaderController.setSummary(mAccessPoint.getSettingsSummary())
|
||||
.done(mFragment.getActivity(), true /* rebind */);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
// Ensure mNetwork is set before any callbacks above are delivered, since our
|
||||
@@ -360,9 +387,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
// MAC Address Pref
|
||||
mMacAddressPref.setSummary(mWifiConfig.getRandomizedMacAddress().toString());
|
||||
|
||||
// TODO(b/124700353): Change header to data usage chart
|
||||
mEntityHeaderController.setSummary(mAccessPoint.getSettingsSummary())
|
||||
.done(mFragment.getActivity(), true /* rebind */);
|
||||
refreshEntityHeader();
|
||||
|
||||
updateIpLayerInfo();
|
||||
|
||||
@@ -429,8 +454,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
|
||||
private void refreshNetworkState() {
|
||||
mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
|
||||
mEntityHeaderController.setSummary(mAccessPoint.getSettingsSummary())
|
||||
.done(mFragment.getActivity(), true /* rebind */);
|
||||
refreshEntityHeader();
|
||||
}
|
||||
|
||||
private void refreshRssiViews() {
|
||||
@@ -443,7 +467,10 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
Drawable wifiIcon = mIconInjector.getIcon(mRssiSignalLevel);
|
||||
|
||||
wifiIcon.setTintList(Utils.getColorAccent(mContext));
|
||||
mEntityHeaderController.setIcon(wifiIcon).done(mFragment.getActivity(), true /* rebind */);
|
||||
if (mEntityHeaderController != null) {
|
||||
mEntityHeaderController.setIcon(wifiIcon).done(mFragment.getActivity(),
|
||||
true /* rebind */);
|
||||
}
|
||||
|
||||
Drawable wifiIconDark = wifiIcon.getConstantState().newDrawable().mutate();
|
||||
wifiIconDark.setTintList(Utils.getColorAttr(mContext, android.R.attr.colorControlNormal));
|
||||
@@ -670,4 +697,8 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
|
||||
return mContext.getDrawable(Utils.getWifiIconResource(level)).mutate();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean usingDataUsageHeader(Context context) {
|
||||
return FeatureFlagUtils.isEnabled(context, FeatureFlags.WIFI_DETAILS_DATAUSAGE_HEADER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,11 +153,11 @@ public class WifiNetworkDetailsFragment extends DashboardFragment {
|
||||
|
||||
controllers.add(mWifiDetailPreferenceController);
|
||||
controllers.add(new WifiMeteredPreferenceController(context, mAccessPoint.getConfig()));
|
||||
WifiPrivacyPreferenceController preferenceController = new WifiPrivacyPreferenceController(
|
||||
WifiPrivacyPreferenceController privacyController = new WifiPrivacyPreferenceController(
|
||||
context);
|
||||
preferenceController.setWifiConfiguration(mAccessPoint.getConfig());
|
||||
preferenceController.setIsEphemeral(mAccessPoint.isEphemeral());
|
||||
controllers.add(preferenceController);
|
||||
privacyController.setWifiConfiguration(mAccessPoint.getConfig());
|
||||
privacyController.setIsEphemeral(mAccessPoint.isEphemeral());
|
||||
controllers.add(privacyController);
|
||||
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public class WifiPrivacyPreferenceController extends BasePreferenceController im
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_wifi_p2p_mac_randomization_supported) ?
|
||||
com.android.internal.R.bool.config_wifi_connected_mac_randomization_supported) ?
|
||||
AVAILABLE : CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
|
||||
@@ -199,11 +199,7 @@ public class SavedAccessPointsWifiSettings extends DashboardFragment
|
||||
* Checks if showing WifiNetworkDetailsFragment when clicking saved network item.
|
||||
*/
|
||||
public static boolean usingDetailsFragment(Context context) {
|
||||
if (FeatureFlagUtils.isEnabled(context, FeatureFlags.MOBILE_NETWORK_V2)
|
||||
&& FeatureFlagPersistent.isEnabled(context, FeatureFlags.NETWORK_INTERNET_V2)) {
|
||||
return false; // TODO(b/124695272): mark true when UI is ready.
|
||||
}
|
||||
return false;
|
||||
return FeatureFlagUtils.isEnabled(context, FeatureFlags.WIFI_DETAILS_SAVED_SCREEN);
|
||||
}
|
||||
|
||||
boolean isSubscriptionsFeatureEnabled() {
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.util.Log;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.slice.Slice;
|
||||
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.slices.CustomSliceRegistry;
|
||||
import com.android.settings.slices.CustomSliceable;
|
||||
|
||||
@@ -35,7 +36,9 @@ public class ContextualWifiSlice extends WifiSlice {
|
||||
|
||||
private static final String TAG = "ContextualWifiSlice";
|
||||
@VisibleForTesting
|
||||
boolean mPreviouslyDisplayed;
|
||||
static long sActiveUiSession = -1000;
|
||||
@VisibleForTesting
|
||||
static boolean sPreviouslyDisplayed;
|
||||
|
||||
public ContextualWifiSlice(Context context) {
|
||||
super(context);
|
||||
@@ -48,13 +51,19 @@ public class ContextualWifiSlice extends WifiSlice {
|
||||
|
||||
@Override
|
||||
public Slice getSlice() {
|
||||
if (!mPreviouslyDisplayed && !TextUtils.equals(getActiveSSID(), WifiSsid.NONE)) {
|
||||
final long currentUiSession = FeatureFactory.getFactory(mContext)
|
||||
.getSlicesFeatureProvider().getUiSessionToken();
|
||||
if (currentUiSession != sActiveUiSession) {
|
||||
sActiveUiSession = currentUiSession;
|
||||
sPreviouslyDisplayed = false;
|
||||
}
|
||||
if (!sPreviouslyDisplayed && !TextUtils.equals(getActiveSSID(), WifiSsid.NONE)) {
|
||||
Log.d(TAG, "Wifi is connected, no point showing any suggestion.");
|
||||
return null;
|
||||
}
|
||||
// Set mPreviouslyDisplayed to true - we will show *something* on the screen. So we should
|
||||
// Set sPreviouslyDisplayed to true - we will show *something* on the screen. So we should
|
||||
// keep showing this card to keep UI stable, even if wifi connects to a network later.
|
||||
mPreviouslyDisplayed = true;
|
||||
sPreviouslyDisplayed = true;
|
||||
|
||||
return super.getSlice();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ com.android.settings.applications.appinfo.InstantAppButtonsPreferenceController
|
||||
com.android.settings.bluetooth.BluetoothDeviceNamePreferenceController
|
||||
com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController
|
||||
com.android.settings.datausage.DataUsageSummaryPreferenceController
|
||||
com.android.settings.datausage.WifiDataUsageSummaryPreferenceController
|
||||
com.android.settings.fuelgauge.RestrictAppPreferenceController
|
||||
com.android.settings.fuelgauge.batterysaver.BatterySaverButtonPreferenceController
|
||||
com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController
|
||||
|
||||
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@@ -55,6 +56,7 @@ import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.shadows.ShadowActivityManager;
|
||||
import org.robolectric.shadows.ShadowContentResolver;
|
||||
import org.robolectric.shadows.ShadowPackageManager;
|
||||
|
||||
@@ -100,6 +102,19 @@ public class AvatarViewMixinTest {
|
||||
verify(mixin, never()).hasAccount();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_lowRamDevice_doNothing() {
|
||||
final AvatarViewMixin mixin = spy(new AvatarViewMixin(mActivity, mImageView));
|
||||
|
||||
final ShadowActivityManager activityManager =
|
||||
Shadow.extract(mContext.getSystemService(ActivityManager.class));
|
||||
activityManager.setIsLowRamDevice(true);
|
||||
|
||||
mixin.onStart();
|
||||
|
||||
verify(mixin, never()).hasAccount();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "mcc999",
|
||||
shadows = {
|
||||
|
||||
@@ -164,7 +164,8 @@ public class DataUsageSummaryPreferenceControllerTest {
|
||||
verify(mSummaryPreference).setUsageInfo(info.cycleEnd, now - UPDATE_BACKOFF_MS,
|
||||
CARRIER_NAME, 1 /* numPlans */, intent);
|
||||
verify(mSummaryPreference).setChartEnabled(true);
|
||||
verify(mSummaryPreference).setWifiMode(false, null);
|
||||
verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */,
|
||||
false /* isSingleWifi */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -188,7 +189,8 @@ public class DataUsageSummaryPreferenceControllerTest {
|
||||
verify(mSummaryPreference).setUsageInfo(info.cycleEnd, now - UPDATE_BACKOFF_MS,
|
||||
CARRIER_NAME, 0 /* numPlans */, intent);
|
||||
verify(mSummaryPreference).setChartEnabled(true);
|
||||
verify(mSummaryPreference).setWifiMode(false, null);
|
||||
verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */,
|
||||
false /* isSingleWifi */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -214,7 +216,8 @@ public class DataUsageSummaryPreferenceControllerTest {
|
||||
0 /* numPlans */,
|
||||
null /* launchIntent */);
|
||||
verify(mSummaryPreference).setChartEnabled(true);
|
||||
verify(mSummaryPreference).setWifiMode(false, null);
|
||||
verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */,
|
||||
false /* isSingleWifi */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -240,7 +243,8 @@ public class DataUsageSummaryPreferenceControllerTest {
|
||||
0 /* numPlans */,
|
||||
null /* launchIntent */);
|
||||
verify(mSummaryPreference).setChartEnabled(false);
|
||||
verify(mSummaryPreference).setWifiMode(false, null);
|
||||
verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */,
|
||||
false /* isSingleWifi */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -321,7 +325,8 @@ public class DataUsageSummaryPreferenceControllerTest {
|
||||
verify(mSummaryPreference).setLimitInfo(captor.capture());
|
||||
CharSequence value = captor.getValue();
|
||||
assertThat(value.toString()).isEqualTo("1.00 MB data warning / 1.00 MB data limit");
|
||||
verify(mSummaryPreference).setWifiMode(false, null);
|
||||
verify(mSummaryPreference).setWifiMode(false /* isWifiMode */, null /* usagePeriod */,
|
||||
false /* isSingleWifi */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -340,7 +345,8 @@ public class DataUsageSummaryPreferenceControllerTest {
|
||||
when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_ABSENT);
|
||||
mController.updateState(mSummaryPreference);
|
||||
|
||||
verify(mSummaryPreference).setWifiMode(true, info.period);
|
||||
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);
|
||||
|
||||
@@ -488,7 +488,7 @@ public class DataUsageSummaryPreferenceTest {
|
||||
new Intent());
|
||||
mSummaryPreference.setUsageNumbers(1000000L, -1L, true);
|
||||
final String cycleText = "The quick fox";
|
||||
mSummaryPreference.setWifiMode(true, cycleText);
|
||||
mSummaryPreference.setWifiMode(true /* isWifiMode */, cycleText, false /* isSingleWifi */);
|
||||
doReturn(200L).when(mSummaryPreference).getHistoricalUsageLevel();
|
||||
|
||||
bindViewHolder();
|
||||
@@ -524,7 +524,8 @@ public class DataUsageSummaryPreferenceTest {
|
||||
@Test
|
||||
public void testSetWifiMode_noUsageInfo_shouldDisableLaunchButton() {
|
||||
mSummaryPreference = spy(mSummaryPreference);
|
||||
mSummaryPreference.setWifiMode(true, "Test cycle text");
|
||||
mSummaryPreference.setWifiMode(true /* isWifiMode */, "Test cycle text",
|
||||
false /* isSingleWifi */);
|
||||
doReturn(0L).when(mSummaryPreference).getHistoricalUsageLevel();
|
||||
|
||||
bindViewHolder();
|
||||
|
||||
@@ -94,13 +94,13 @@ public class BatterySaverButtonPreferenceControllerTest {
|
||||
public void setChecked_on_setPowerSaveMode() {
|
||||
mController.setChecked(true);
|
||||
|
||||
verify(mPowerManager).setPowerSaveMode(true);
|
||||
verify(mPowerManager).setPowerSaveModeEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_off_unsetPowerSaveMode() {
|
||||
mController.setChecked(false);
|
||||
|
||||
verify(mPowerManager).setPowerSaveMode(false);
|
||||
verify(mPowerManager).setPowerSaveModeEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -31,6 +32,7 @@ import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.euicc.EuiccManager;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -50,6 +52,9 @@ import androidx.preference.PreferenceScreen;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class MobileNetworkListControllerTest {
|
||||
@Mock
|
||||
EuiccManager mEuiccManager;
|
||||
|
||||
@Mock
|
||||
private Lifecycle mLifecycle;
|
||||
|
||||
@@ -58,12 +63,17 @@ public class MobileNetworkListControllerTest {
|
||||
|
||||
private Context mContext;
|
||||
private MobileNetworkListController mController;
|
||||
private Preference mAddMorePreference;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(Robolectric.setupActivity(Activity.class));
|
||||
when(mContext.getSystemService(EuiccManager.class)).thenReturn(mEuiccManager);
|
||||
when(mPreferenceScreen.getContext()).thenReturn(mContext);
|
||||
mAddMorePreference = new Preference(mContext);
|
||||
when(mPreferenceScreen.findPreference(MobileNetworkListController.KEY_ADD_MORE)).thenReturn(
|
||||
mAddMorePreference);
|
||||
mController = new MobileNetworkListController(mContext, mLifecycle);
|
||||
}
|
||||
|
||||
@@ -78,6 +88,22 @@ public class MobileNetworkListControllerTest {
|
||||
mController.onResume();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_eSimNotSupported_addMoreLinkNotVisible() {
|
||||
when(mEuiccManager.isEnabled()).thenReturn(false);
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.onResume();
|
||||
assertThat(mAddMorePreference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_eSimSupported_addMoreLinkIsVisible() {
|
||||
when(mEuiccManager.isEnabled()).thenReturn(true);
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.onResume();
|
||||
assertThat(mAddMorePreference.isVisible()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_twoSubscriptions_correctlySetup() {
|
||||
final SubscriptionInfo sub1 = createMockSubscription(1, "sub1");
|
||||
|
||||
@@ -16,13 +16,9 @@
|
||||
|
||||
package com.android.settings.network;
|
||||
|
||||
import static android.telephony.TelephonyManager.MultiSimVariants.DSDS;
|
||||
import static android.telephony.TelephonyManager.MultiSimVariants.UNKNOWN;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.ArgumentMatchers.notNull;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -37,7 +33,6 @@ import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.telephony.euicc.EuiccManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
@@ -64,8 +59,6 @@ public class MobileNetworkSummaryControllerTest {
|
||||
@Mock
|
||||
private Lifecycle mLifecycle;
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyManager;
|
||||
@Mock
|
||||
private EuiccManager mEuiccManager;
|
||||
@Mock
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
@@ -78,9 +71,7 @@ public class MobileNetworkSummaryControllerTest {
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(Robolectric.setupActivity(Activity.class));
|
||||
when(mContext.getSystemService(eq(TelephonyManager.class))).thenReturn(mTelephonyManager);
|
||||
when(mContext.getSystemService(EuiccManager.class)).thenReturn(mEuiccManager);
|
||||
when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(UNKNOWN);
|
||||
when(mEuiccManager.isEnabled()).thenReturn(true);
|
||||
|
||||
mController = new MobileNetworkSummaryController(mContext, mLifecycle);
|
||||
@@ -97,7 +88,7 @@ public class MobileNetworkSummaryControllerTest {
|
||||
|
||||
@Test
|
||||
public void isAvailable_wifiOnlyMode_notAvailable() {
|
||||
ConnectivityManager cm = mock(ConnectivityManager.class);
|
||||
final ConnectivityManager cm = mock(ConnectivityManager.class);
|
||||
when(cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
|
||||
when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(cm);
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
@@ -212,24 +203,7 @@ public class MobileNetworkSummaryControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addButton_noSubscriptionsSingleSimMode_noAddClickListener() {
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.onResume();
|
||||
verify(mPreference, never()).setOnAddClickListener(notNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addButton_oneSubscriptionSingleSimMode_noAddClickListener() {
|
||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
||||
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.onResume();
|
||||
verify(mPreference, never()).setOnAddClickListener(notNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addButton_noSubscriptionsMultiSimModeNoEuiccMgr_noAddClickListener() {
|
||||
when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
|
||||
public void addButton_noSubscriptionsNoEuiccMgr_noAddClickListener() {
|
||||
when(mEuiccManager.isEnabled()).thenReturn(false);
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.onResume();
|
||||
@@ -237,41 +211,43 @@ public class MobileNetworkSummaryControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addButton_noSubscriptionsMultiSimMode_hasAddClickListenerAndPrefDisabled() {
|
||||
when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.onResume();
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
verify(mPreference, never()).setOnAddClickListener(isNull());
|
||||
verify(mPreference).setOnAddClickListener(notNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addButton_oneSubscriptionMultiSimMode_hasAddClickListener() {
|
||||
when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
|
||||
public void addButton_oneSubscriptionNoEuiccMgr_noAddClickListener() {
|
||||
when(mEuiccManager.isEnabled()).thenReturn(false);
|
||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
||||
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.onResume();
|
||||
verify(mPreference, never()).setOnAddClickListener(notNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addButton_noSubscriptions_noAddClickListener() {
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.onResume();
|
||||
verify(mPreference, never()).setOnAddClickListener(notNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addButton_oneSubscription_hasAddClickListener() {
|
||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
||||
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.onResume();
|
||||
verify(mPreference, never()).setOnAddClickListener(isNull());
|
||||
verify(mPreference).setOnAddClickListener(notNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addButton_twoSubscriptionsMultiSimMode_hasAddClickListener() {
|
||||
when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
|
||||
public void addButton_twoSubscriptions_hasAddClickListener() {
|
||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
||||
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
|
||||
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
mController.onResume();
|
||||
verify(mPreference, never()).setOnAddClickListener(isNull());
|
||||
verify(mPreference).setOnAddClickListener(notNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addButton_oneSubscriptionAirplaneModeTurnedOn_addButtonGetsDisabled() {
|
||||
when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
|
||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
||||
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
@@ -280,14 +256,13 @@ public class MobileNetworkSummaryControllerTest {
|
||||
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
|
||||
mController.onAirplaneModeChanged(true);
|
||||
|
||||
ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
|
||||
final ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
|
||||
verify(mPreference, atLeastOnce()).setAddWidgetEnabled(captor.capture());
|
||||
assertThat(captor.getValue()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onResume_oneSubscriptionAirplaneMode_isDisabled() {
|
||||
when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
|
||||
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
|
||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
||||
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
|
||||
@@ -296,7 +271,7 @@ public class MobileNetworkSummaryControllerTest {
|
||||
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
|
||||
ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
|
||||
final ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
|
||||
verify(mPreference, atLeastOnce()).setAddWidgetEnabled(captor.capture());
|
||||
assertThat(captor.getValue()).isFalse();
|
||||
}
|
||||
@@ -318,7 +293,6 @@ public class MobileNetworkSummaryControllerTest {
|
||||
|
||||
@Test
|
||||
public void onAirplaneModeChanged_oneSubscriptionAirplaneModeGetsTurnedOff_isEnabled() {
|
||||
when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(DSDS);
|
||||
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
|
||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
||||
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
|
||||
@@ -332,7 +306,7 @@ public class MobileNetworkSummaryControllerTest {
|
||||
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
|
||||
ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
|
||||
final ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
|
||||
verify(mPreference, atLeastOnce()).setAddWidgetEnabled(eq(false));
|
||||
verify(mPreference, atLeastOnce()).setAddWidgetEnabled(captor.capture());
|
||||
assertThat(captor.getValue()).isTrue();
|
||||
|
||||
@@ -22,7 +22,6 @@ import static android.app.slice.SliceItem.FORMAT_TEXT;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -43,7 +42,6 @@ import androidx.slice.widget.SliceLiveData;
|
||||
|
||||
import com.android.ims.ImsManager;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.slices.CustomSliceManager;
|
||||
import com.android.settings.slices.CustomSliceRegistry;
|
||||
import com.android.settings.slices.SettingsSliceProvider;
|
||||
import com.android.settings.slices.SliceBroadcastReceiver;
|
||||
@@ -85,10 +83,6 @@ public class Enhanced4gLteSliceHelperTest {
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mSlicesFeatureProvider = mFeatureFactory.getSlicesFeatureProvider();
|
||||
|
||||
CustomSliceManager manager = new CustomSliceManager(mContext);
|
||||
when(mSlicesFeatureProvider.getCustomSliceManager(any(Context.class)))
|
||||
.thenReturn(manager);
|
||||
|
||||
//setup for SettingsSliceProvider tests
|
||||
mProvider = spy(new SettingsSliceProvider());
|
||||
doReturn(mContext).when(mProvider).getContext();
|
||||
|
||||
@@ -110,6 +110,26 @@ public class BlockPreferenceControllerTest {
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_notIfChannelNonDefault() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.systemApp = true;
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_ifChannelDefault() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
|
||||
when(channel.getId()).thenReturn(DEFAULT_CHANNEL_ID);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
assertTrue(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_notIfGroupNotBlockable() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
import static android.app.NotificationManager.IMPORTANCE_HIGH;
|
||||
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.shadows.ShadowApplication;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class HighImportancePreferenceControllerTest {
|
||||
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private NotificationManager mNm;
|
||||
@Mock
|
||||
private NotificationBackend mBackend;
|
||||
@Mock
|
||||
private NotificationSettingsBase.ImportanceListener mImportanceListener;
|
||||
@Mock
|
||||
private UserManager mUm;
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
private HighImportancePreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
ShadowApplication shadowApplication = ShadowApplication.getInstance();
|
||||
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
|
||||
shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mController = spy(new HighImportancePreferenceController(
|
||||
mContext, mImportanceListener, mBackend));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoCrashIfNoOnResume() {
|
||||
mController.isAvailable();
|
||||
mController.updateState(mock(Preference.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_notIfNull() {
|
||||
mController.onResume(null, null, null, null);
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_ifAppBlocked() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.banned = true;
|
||||
mController.onResume(appRow, mock(NotificationChannel.class), null, null);
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_notIfChannelBlocked() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_NONE);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_notForDefaultChannel() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
|
||||
when(channel.getId()).thenReturn(DEFAULT_CHANNEL_ID);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_DEFAULT);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
assertTrue(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_disabledByAdmin() {
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
|
||||
mController.onResume(new NotificationBackend.AppRow(), channel, null, mock(
|
||||
RestrictedLockUtils.EnforcedAdmin.class));
|
||||
|
||||
Preference pref = new RestrictedSwitchPreference(mContext, null);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_notConfigurable() {
|
||||
String lockedId = "locked";
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.lockedChannelId = lockedId;
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getId()).thenReturn(lockedId);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
|
||||
Preference pref = new RestrictedSwitchPreference(mContext, null);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_high() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
|
||||
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertTrue(pref.isChecked());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_default() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
|
||||
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isChecked());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange() {
|
||||
NotificationChannel channel =
|
||||
new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_HIGH);
|
||||
mController.onResume(new NotificationBackend.AppRow(), channel, null, null);
|
||||
|
||||
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext, null);
|
||||
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
|
||||
mController.displayPreference(mScreen);
|
||||
mController.updateState(pref);
|
||||
|
||||
mController.onPreferenceChange(pref, false);
|
||||
|
||||
assertEquals(IMPORTANCE_DEFAULT, channel.getImportance());
|
||||
verify(mImportanceListener, times(1)).onImportanceChanged();
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,11 @@ import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Notification;
|
||||
@@ -36,12 +39,10 @@ import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.os.UserManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.RestrictedListPreference;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -95,20 +96,20 @@ public class ImportancePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_notIfAppBlocked() {
|
||||
public void testIsAvailable_ifAppBlocked() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.banned = true;
|
||||
mController.onResume(appRow, mock(NotificationChannel.class), null, null);
|
||||
assertFalse(mController.isAvailable());
|
||||
assertTrue(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_notIfChannelBlocked() {
|
||||
public void testIsAvailable_evenIfChannelBlocked() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_NONE);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
assertFalse(mController.isAvailable());
|
||||
assertTrue(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -137,11 +138,10 @@ public class ImportancePreferenceControllerTest {
|
||||
mController.onResume(new NotificationBackend.AppRow(), channel, null, mock(
|
||||
RestrictedLockUtils.EnforcedAdmin.class));
|
||||
|
||||
Preference pref = new RestrictedListPreference(mContext, null);
|
||||
Preference pref = new ImportancePreference(mContext, null);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
assertFalse(TextUtils.isEmpty(pref.getSummary()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -154,11 +154,10 @@ public class ImportancePreferenceControllerTest {
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
|
||||
Preference pref = new RestrictedListPreference(mContext, null);
|
||||
Preference pref = new ImportancePreference(mContext, null);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
assertFalse(TextUtils.isEmpty(pref.getSummary()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -167,11 +166,12 @@ public class ImportancePreferenceControllerTest {
|
||||
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
|
||||
Preference pref = new RestrictedListPreference(mContext, null);
|
||||
ImportancePreference pref = mock(ImportancePreference.class);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertTrue(pref.isEnabled());
|
||||
assertFalse(TextUtils.isEmpty(pref.getSummary()));
|
||||
verify(pref, times(1)).setConfigurable(anyBoolean());
|
||||
verify(pref, times(1)).setBlockable(anyBoolean());
|
||||
verify(pref, times(1)).setImportance(IMPORTANCE_HIGH);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -181,13 +181,12 @@ public class ImportancePreferenceControllerTest {
|
||||
channel.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
|
||||
mController.onResume(new NotificationBackend.AppRow(), channel, null, null);
|
||||
|
||||
RestrictedListPreference pref = new RestrictedListPreference(mContext, null);
|
||||
ImportancePreference pref = new ImportancePreference(mContext, null);
|
||||
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
|
||||
mController.displayPreference(mScreen);
|
||||
mController.updateState(pref);
|
||||
|
||||
pref.setValue(String.valueOf(IMPORTANCE_HIGH));
|
||||
mController.onPreferenceChange(pref, pref.getValue());
|
||||
mController.onPreferenceChange(pref, IMPORTANCE_HIGH);
|
||||
|
||||
assertEquals(IMPORTANCE_HIGH, channel.getImportance());
|
||||
assertNotNull(channel.getSound());
|
||||
@@ -200,13 +199,12 @@ public class ImportancePreferenceControllerTest {
|
||||
channel.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
|
||||
mController.onResume(new NotificationBackend.AppRow(), channel, null, null);
|
||||
|
||||
RestrictedListPreference pref = new RestrictedListPreference(mContext, null);
|
||||
ImportancePreference pref = new ImportancePreference(mContext, null);
|
||||
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
|
||||
mController.displayPreference(mScreen);
|
||||
mController.updateState(pref);
|
||||
|
||||
pref.setValue(String.valueOf(IMPORTANCE_LOW));
|
||||
mController.onPreferenceChange(pref, pref.getValue());
|
||||
mController.onPreferenceChange(pref, IMPORTANCE_LOW);
|
||||
|
||||
assertEquals(IMPORTANCE_LOW, channel.getImportance());
|
||||
assertNull(channel.getSound());
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Switch;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ImportancePreferenceTest {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
}
|
||||
|
||||
private GradientDrawable getBackground(ImageButton button) {
|
||||
return (GradientDrawable) ((LayerDrawable) button.getDrawable())
|
||||
.findDrawableByLayerId(R.id.back);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewPreference_shouldSetLayout() {
|
||||
final ImportancePreference preference = new ImportancePreference(mContext);
|
||||
assertThat(preference.getLayoutResource()).isEqualTo(
|
||||
R.layout.notif_importance_preference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_hideBlockNonBlockable() {
|
||||
final ImportancePreference preference = new ImportancePreference(mContext);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.notif_importance_preference, null));
|
||||
|
||||
preference.setBlockable(false);
|
||||
preference.setConfigurable(true);
|
||||
preference.setImportance(IMPORTANCE_DEFAULT);
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
assertThat(holder.itemView.findViewById(R.id.block).getVisibility()).isEqualTo(View.GONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_hideNonSelectedNonConfigurable() {
|
||||
final ImportancePreference preference = new ImportancePreference(mContext);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.notif_importance_preference, null));
|
||||
|
||||
preference.setBlockable(true);
|
||||
preference.setConfigurable(false);
|
||||
preference.setImportance(IMPORTANCE_DEFAULT);
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
assertThat(holder.itemView.findViewById(R.id.block).getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(holder.itemView.findViewById(R.id.silence).getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(holder.itemView.findViewById(R.id.alert).getVisibility())
|
||||
.isEqualTo(View.VISIBLE);
|
||||
|
||||
// other button
|
||||
preference.setImportance(IMPORTANCE_LOW);
|
||||
holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.notif_importance_preference, null));
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
assertThat(holder.itemView.findViewById(R.id.block).getVisibility()).isEqualTo(View.GONE);
|
||||
assertThat(holder.itemView.findViewById(R.id.silence).getVisibility())
|
||||
.isEqualTo(View.VISIBLE);
|
||||
assertThat(holder.itemView.findViewById(R.id.alert).getVisibility())
|
||||
.isEqualTo(View.GONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_selectButton() {
|
||||
final ImportancePreference preference = new ImportancePreference(mContext);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.notif_importance_preference, null));
|
||||
|
||||
preference.setBlockable(true);
|
||||
preference.setConfigurable(true);
|
||||
preference.setImportance(IMPORTANCE_DEFAULT);
|
||||
|
||||
ImageButton blockButton = (ImageButton) holder.findViewById(R.id.block_icon);
|
||||
ImageButton silenceButton = (ImageButton) holder.findViewById(R.id.silence_icon);
|
||||
ImageButton alertButton = (ImageButton) holder.findViewById(R.id.alert_icon);
|
||||
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
// selected has full color background. others are transparent
|
||||
assertThat(getBackground(alertButton).getColor().getColors()[0]).isNotEqualTo(
|
||||
Color.TRANSPARENT);
|
||||
assertThat(getBackground(silenceButton).getColor().getColors()[0]).isEqualTo(
|
||||
Color.TRANSPARENT);
|
||||
assertThat(getBackground(blockButton).getColor().getColors()[0]).isEqualTo(
|
||||
Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onClick_changesUICallsListener() {
|
||||
final ImportancePreference preference = spy(new ImportancePreference(mContext));
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.notif_importance_preference, null));
|
||||
|
||||
preference.setBlockable(true);
|
||||
preference.setConfigurable(true);
|
||||
preference.setImportance(IMPORTANCE_DEFAULT);
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
ImageButton blockButton = (ImageButton) holder.findViewById(R.id.block_icon);
|
||||
ImageButton silenceButton = (ImageButton) holder.findViewById(R.id.silence_icon);
|
||||
ImageButton alertButton = (ImageButton) holder.findViewById(R.id.alert_icon);
|
||||
|
||||
silenceButton.callOnClick();
|
||||
|
||||
// selected has full color background. others are transparent
|
||||
assertThat(getBackground(silenceButton).getColor().getColors()[0]).isNotEqualTo(
|
||||
Color.TRANSPARENT);
|
||||
assertThat(getBackground(alertButton).getColor().getColors()[0]).isEqualTo(
|
||||
Color.TRANSPARENT);
|
||||
assertThat(getBackground(blockButton).getColor().getColors()[0]).isEqualTo(
|
||||
Color.TRANSPARENT);
|
||||
|
||||
verify(preference, times(1)).callChangeListener(IMPORTANCE_LOW);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_allButtonsVisible() {
|
||||
final ImportancePreference preference = new ImportancePreference(mContext);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.notif_importance_preference, null));
|
||||
|
||||
preference.setBlockable(true);
|
||||
preference.setConfigurable(true);
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
assertThat(holder.itemView.findViewById(R.id.block).getVisibility())
|
||||
.isEqualTo(View.VISIBLE);
|
||||
assertThat(holder.itemView.findViewById(R.id.silence).getVisibility())
|
||||
.isEqualTo(View.VISIBLE);
|
||||
assertThat(holder.itemView.findViewById(R.id.alert).getVisibility())
|
||||
.isEqualTo(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
|
||||
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||
import static android.app.NotificationManager.IMPORTANCE_MIN;
|
||||
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.shadows.ShadowApplication;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class MinImportancePreferenceControllerTest {
|
||||
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private NotificationManager mNm;
|
||||
@Mock
|
||||
private NotificationBackend mBackend;
|
||||
@Mock
|
||||
private NotificationSettingsBase.ImportanceListener mImportanceListener;
|
||||
@Mock
|
||||
private UserManager mUm;
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
private MinImportancePreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
ShadowApplication shadowApplication = ShadowApplication.getInstance();
|
||||
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
|
||||
shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mController = spy(new MinImportancePreferenceController(
|
||||
mContext, mImportanceListener, mBackend));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoCrashIfNoOnResume() {
|
||||
mController.isAvailable();
|
||||
mController.updateState(mock(Preference.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_notIfNull() {
|
||||
mController.onResume(null, null, null, null);
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_ifAppBlocked() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.banned = true;
|
||||
mController.onResume(appRow, mock(NotificationChannel.class), null, null);
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_notIfChannelBlocked() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_NONE);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable_notForDefaultChannel() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
|
||||
when(channel.getId()).thenReturn(DEFAULT_CHANNEL_ID);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
assertFalse(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAvailable() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
assertTrue(mController.isAvailable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_disabledByAdmin() {
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
|
||||
mController.onResume(new NotificationBackend.AppRow(), channel, null, mock(
|
||||
RestrictedLockUtils.EnforcedAdmin.class));
|
||||
|
||||
Preference pref = new RestrictedSwitchPreference(mContext, null);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_notConfigurable() {
|
||||
String lockedId = "locked";
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.lockedChannelId = lockedId;
|
||||
NotificationChannel channel = mock(NotificationChannel.class);
|
||||
when(channel.getId()).thenReturn(lockedId);
|
||||
when(channel.getImportance()).thenReturn(IMPORTANCE_LOW);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
|
||||
Preference pref = new RestrictedSwitchPreference(mContext, null);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_min() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_MIN);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
|
||||
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertTrue(pref.isChecked());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_low() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_LOW);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
|
||||
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
|
||||
mController.updateState(pref);
|
||||
|
||||
assertFalse(pref.isChecked());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange() {
|
||||
NotificationChannel channel =
|
||||
new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_LOW);
|
||||
mController.onResume(new NotificationBackend.AppRow(), channel, null, null);
|
||||
|
||||
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext, null);
|
||||
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
|
||||
mController.displayPreference(mScreen);
|
||||
mController.updateState(pref);
|
||||
|
||||
mController.onPreferenceChange(pref, true);
|
||||
|
||||
assertEquals(IMPORTANCE_MIN, channel.getImportance());
|
||||
verify(mImportanceListener, times(1)).onImportanceChanged();
|
||||
}
|
||||
}
|
||||
@@ -218,6 +218,20 @@ public class NotificationPreferenceControllerTest {
|
||||
assertTrue(mController.isChannelConfigurable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsConfigurable_appLevel() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.lockedChannelId = "something";
|
||||
appRow.lockedImportance = true;
|
||||
|
||||
mController.onResume(appRow, mock(NotificationChannel.class), null, null);
|
||||
assertFalse(mController.isChannelConfigurable());
|
||||
|
||||
appRow.lockedImportance = false;
|
||||
mController.onResume(appRow, mock(NotificationChannel.class), null, null);
|
||||
assertTrue(mController.isChannelConfigurable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsChannelBlockable_nonSystemAppsBlockable() {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
|
||||
@@ -135,7 +135,6 @@ public class SettingsSliceProviderTest {
|
||||
mProvider.mSliceWeakDataCache = new HashMap<>();
|
||||
mProvider.mSliceDataCache = new HashMap<>();
|
||||
mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
|
||||
mProvider.mCustomSliceManager = new CustomSliceManager(mContext);
|
||||
when(mProvider.getContext()).thenReturn(mContext);
|
||||
|
||||
SlicesDatabaseHelper.getInstance(mContext).setIndexedState();
|
||||
|
||||
@@ -19,14 +19,12 @@ package com.android.settings.slices;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.app.slice.Slice;
|
||||
@@ -82,9 +80,6 @@ public class SliceBroadcastReceiverTest {
|
||||
mSearchFeatureProvider = new SearchFeatureProviderImpl();
|
||||
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mFakeFeatureFactory.searchFeatureProvider = mSearchFeatureProvider;
|
||||
CustomSliceManager manager = new CustomSliceManager(mContext);
|
||||
when(mFakeFeatureFactory.slicesFeatureProvider.getCustomSliceManager(any()))
|
||||
.thenReturn(manager);
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
@@ -55,6 +55,7 @@ public class SlicesDatabaseHelperTest {
|
||||
@After
|
||||
public void cleanUp() {
|
||||
DatabaseTestUtils.clearDb(mContext);
|
||||
mDatabase.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -19,8 +19,6 @@ package com.android.settings.slices;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -39,30 +37,36 @@ import org.robolectric.RuntimeEnvironment;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class SpecialCaseSliceManagerTest {
|
||||
|
||||
private Context mContext;
|
||||
private final String FAKE_PARAMETER_KEY = "fake_parameter_key";
|
||||
private final String FAKE_PARAMETER_VALUE = "fake_value";
|
||||
|
||||
private CustomSliceManager mCustomSliceManager;
|
||||
private Context mContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mCustomSliceManager = spy(new CustomSliceManager(mContext));
|
||||
CustomSliceRegistry.sUriToSlice.clear();
|
||||
CustomSliceRegistry.sUriToSlice.put(FakeSliceable.URI, FakeSliceable.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSliceableFromUri_returnsCorrectObject() {
|
||||
final CustomSliceable sliceable = mCustomSliceManager.getSliceableFromUri(
|
||||
FakeSliceable.URI);
|
||||
final CustomSliceable sliceable = CustomSliceable.createInstance(
|
||||
mContext, CustomSliceRegistry.getSliceClassByUri(FakeSliceable.URI));
|
||||
|
||||
assertThat(sliceable).isInstanceOf(FakeSliceable.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSliceableFromIntentAction_returnsCorrectObject() {
|
||||
final CustomSliceable sliceable =
|
||||
mCustomSliceManager.getSliceableFromIntentAction(FakeSliceable.URI.toString());
|
||||
public void getSliceableFromUriWithParameter_returnsCorrectObject() {
|
||||
final Uri parameterUri = FakeSliceable.URI
|
||||
.buildUpon()
|
||||
.clearQuery()
|
||||
.appendQueryParameter(FAKE_PARAMETER_KEY, FAKE_PARAMETER_VALUE)
|
||||
.build();
|
||||
|
||||
final CustomSliceable sliceable = CustomSliceable.createInstance(
|
||||
mContext, CustomSliceRegistry.getSliceClassByUri(parameterUri));
|
||||
|
||||
assertThat(sliceable).isInstanceOf(FakeSliceable.class);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.testutils.shadow;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.wifi.calling.DisclaimerItemFactory;
|
||||
import com.android.settings.wifi.calling.DisclaimerItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
|
||||
@Implements(DisclaimerItemFactory.class)
|
||||
public final class ShadowDisclaimerItemFactory {
|
||||
private static List<DisclaimerItem> sMockDisclaimerItemList;
|
||||
|
||||
public static void setDisclaimerItemList(List<DisclaimerItem> list) {
|
||||
sMockDisclaimerItemList = list;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public static List<DisclaimerItem> create(Context context, int subId) {
|
||||
return sMockDisclaimerItemList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi.calling;
|
||||
|
||||
import static com.android.settings.wifi.calling.DisclaimerItemListAdapter
|
||||
.DisclaimerItemViewHolder.ID_DISCLAIMER_ITEM_TITLE;
|
||||
import static com.android.settings.wifi.calling.DisclaimerItemListAdapter
|
||||
.DisclaimerItemViewHolder.ID_DISCLAIMER_ITEM_DESCRIPTION;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
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;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class DisclaimerItemListAdapterTest {
|
||||
|
||||
private static final int ITEM_POSITION = 0;
|
||||
private static final int DISCLAIMER_TITLE_STRING_ID = 0;
|
||||
private static final int DISCLAIMER_MESSAGE_STRING_ID = 1;
|
||||
|
||||
@Mock
|
||||
private LayoutInflater mLayoutInflater;
|
||||
@Mock
|
||||
private TextView mTestView;
|
||||
@Mock
|
||||
private TextView mDescView;
|
||||
@Mock
|
||||
private View mView;
|
||||
@Mock
|
||||
private ViewGroup mViewGroup;
|
||||
@Mock
|
||||
private Context mContext;
|
||||
|
||||
private MockDisclaimerItem mDisclaimerItem;
|
||||
private DisclaimerItemListAdapter mDisclaimerItemListAdapter;
|
||||
private List<DisclaimerItem> mDisclaimerItemList = new ArrayList<>();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mDisclaimerItem = spy(new MockDisclaimerItem(mContext, 0 /* subId */));
|
||||
mDisclaimerItemList.add(mDisclaimerItem);
|
||||
|
||||
when(mLayoutInflater.inflate(anyInt(), anyObject(), anyBoolean())).thenReturn(mView);
|
||||
when(mViewGroup.getContext()).thenReturn(mContext);
|
||||
when(mViewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).thenReturn(
|
||||
mLayoutInflater);
|
||||
when(mView.findViewById(ID_DISCLAIMER_ITEM_TITLE)).thenReturn(mTestView);
|
||||
when(mView.findViewById(ID_DISCLAIMER_ITEM_DESCRIPTION)).thenReturn(mDescView);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_haveItem_shouldSetText() {
|
||||
final DisclaimerItemListAdapter.DisclaimerItemViewHolder viewHolder =
|
||||
new DisclaimerItemListAdapter.DisclaimerItemViewHolder(mView);
|
||||
|
||||
mDisclaimerItemListAdapter = new DisclaimerItemListAdapter(mDisclaimerItemList);
|
||||
mDisclaimerItemListAdapter.onCreateViewHolder(mViewGroup, 0 /* viewType */);
|
||||
mDisclaimerItemListAdapter.onBindViewHolder(viewHolder, ITEM_POSITION);
|
||||
|
||||
// Check the text is set when the DisclaimerItem exists.
|
||||
verify(viewHolder.titleView).setText(DISCLAIMER_TITLE_STRING_ID);
|
||||
verify(viewHolder.descriptionView).setText(DISCLAIMER_MESSAGE_STRING_ID);
|
||||
}
|
||||
|
||||
private class MockDisclaimerItem extends DisclaimerItem {
|
||||
MockDisclaimerItem(Context context, int subId) {
|
||||
super(context, subId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleId() {
|
||||
return DISCLAIMER_TITLE_STRING_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getMessageId() {
|
||||
return DISCLAIMER_MESSAGE_STRING_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getName() {
|
||||
return "MockDisclaimerItem";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPrefKey() {
|
||||
return "mock_pref_key";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi.calling;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.shadow.ShadowDisclaimerItemFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = ShadowDisclaimerItemFactory.class)
|
||||
public class WifiCallingDisclaimerFragmentTest {
|
||||
|
||||
@Mock
|
||||
private Activity mActivity;
|
||||
@Mock
|
||||
private DisclaimerItem mDisclaimerItem;
|
||||
@Mock
|
||||
private LayoutInflater mLayoutInflater;
|
||||
@Mock
|
||||
private View mView;
|
||||
@Mock
|
||||
private ViewGroup mViewGroup;
|
||||
@Mock
|
||||
private Button mAgreeButton;
|
||||
@Mock
|
||||
private Button mDisagreeButton;
|
||||
@Mock
|
||||
private RecyclerView mRecyclerView;
|
||||
|
||||
@Captor
|
||||
ArgumentCaptor<OnClickListener> mOnClickListenerCaptor;
|
||||
@Captor
|
||||
ArgumentCaptor<OnScrollListener> mOnScrollListenerCaptor;
|
||||
|
||||
private WifiCallingDisclaimerFragment mFragment;
|
||||
private List<DisclaimerItem> mDisclaimerItemList = new ArrayList<>();
|
||||
private List<DisclaimerItem> mEmptyDisclaimerItemList = new ArrayList<>();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mActivity = Robolectric.setupActivity(Activity.class);
|
||||
mFragment = spy(new WifiCallingDisclaimerFragment());
|
||||
|
||||
doReturn(mActivity).when(mFragment).getActivity();
|
||||
|
||||
when(mLayoutInflater.inflate(anyInt(), anyObject(), anyBoolean())).thenReturn(mView);
|
||||
when(mView.findViewById(R.id.agree_button)).thenReturn(mAgreeButton);
|
||||
when(mView.findViewById(R.id.disagree_button)).thenReturn(mDisagreeButton);
|
||||
when(mView.findViewById(R.id.disclaimer_item_list)).thenReturn(mRecyclerView);
|
||||
when(mView.getId()).thenReturn(R.id.agree_button);
|
||||
|
||||
mOnScrollListenerCaptor = ArgumentCaptor.forClass(OnScrollListener.class);
|
||||
doNothing().when(mRecyclerView).addOnScrollListener(mOnScrollListenerCaptor.capture());
|
||||
mOnClickListenerCaptor = ArgumentCaptor.forClass(OnClickListener.class);
|
||||
doNothing().when(mAgreeButton).setOnClickListener(mOnClickListenerCaptor.capture());
|
||||
|
||||
mDisclaimerItemList.add(mDisclaimerItem);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_notHaveItem_shouldFinishFragment() {
|
||||
ShadowDisclaimerItemFactory.setDisclaimerItemList(mEmptyDisclaimerItemList);
|
||||
|
||||
mFragment.onCreate(null /* savedInstanceState */);
|
||||
|
||||
// Check the fragment is finished when the DisclaimerItemList is empty.
|
||||
verify(mFragment).finish(Activity.RESULT_OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreate_haveItem_shouldNotFinishFragment() {
|
||||
ShadowDisclaimerItemFactory.setDisclaimerItemList(mDisclaimerItemList);
|
||||
|
||||
mFragment.onCreate(null /* savedInstanceState */);
|
||||
|
||||
// Check the fragment is not finished when the DisclaimerItemList is not empty.
|
||||
verify(mFragment, never()).finish(Activity.RESULT_OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onScrolled_canNotScroll_shouldEnableAgreeButton() {
|
||||
ShadowDisclaimerItemFactory.setDisclaimerItemList(mDisclaimerItemList);
|
||||
|
||||
when(mRecyclerView.canScrollVertically(1)).thenReturn(false);
|
||||
|
||||
mFragment.onCreate(null /* savedInstanceState */);
|
||||
mFragment.onCreateView(mLayoutInflater, mViewGroup, null /* savedInstanceState */);
|
||||
|
||||
mOnScrollListenerCaptor.getValue().onScrolled(mRecyclerView, 0, 0);
|
||||
|
||||
// Check the agreeButton is enabled when the view is scrolled to the bottom end.
|
||||
verify(mAgreeButton).setEnabled(true);
|
||||
// Check the OnScrollListener is removed when the view is scrolled to the bottom end.
|
||||
verify(mRecyclerView).removeOnScrollListener(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onScrolled_canScroll_shouldNotEnableAgreeButton() {
|
||||
ShadowDisclaimerItemFactory.setDisclaimerItemList(mDisclaimerItemList);
|
||||
|
||||
when(mRecyclerView.canScrollVertically(1)).thenReturn(true);
|
||||
|
||||
mFragment.onCreate(null /* savedInstanceState */);
|
||||
mFragment.onCreateView(mLayoutInflater, mViewGroup, null /* savedInstanceState */);
|
||||
|
||||
mOnScrollListenerCaptor.getValue().onScrolled(mRecyclerView, 0, 0);
|
||||
|
||||
// Check the agreeButton is not enabled when the view is not scrolled to the bottom end.
|
||||
verify(mAgreeButton, never()).setEnabled(anyBoolean());
|
||||
// Check the OnScrollListener is not removed when the view is not scrolled to
|
||||
// the bottom end.
|
||||
verify(mRecyclerView, never()).removeOnScrollListener(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onClick_agreeButton_shouldFinishFragment() {
|
||||
ShadowDisclaimerItemFactory.setDisclaimerItemList(mDisclaimerItemList);
|
||||
|
||||
mFragment.onCreate(null /* savedInstanceState */);
|
||||
mFragment.onCreateView(mLayoutInflater, mViewGroup, null /* savedInstanceState */);
|
||||
|
||||
mOnClickListenerCaptor.getValue().onClick(mAgreeButton);
|
||||
|
||||
// Check the onAgreed callback is called when "CONTINUE" button is clicked.
|
||||
verify(mDisclaimerItem).onAgreed();
|
||||
// Check the WFC disclaimer fragment is finished when "CONTINUE" button is clicked.
|
||||
verify(mFragment).finish(Activity.RESULT_OK);
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,14 @@
|
||||
|
||||
package com.android.settings.wifi.calling;
|
||||
|
||||
import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.eq;
|
||||
@@ -31,6 +34,8 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@@ -41,18 +46,22 @@ import android.telephony.ims.ProvisioningManager;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.ims.ImsConfig;
|
||||
import com.android.ims.ImsManager;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
import com.android.settings.widget.ToggleSwitch;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
@@ -63,6 +72,8 @@ import org.robolectric.util.ReflectionHelpers;
|
||||
public class WifiCallingSettingsForSubTest {
|
||||
private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
|
||||
private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
|
||||
private static final String TEST_EMERGENCY_ADDRESS_CARRIER_APP =
|
||||
"com.android.settings/.wifi.calling.TestEmergencyAddressCarrierApp";
|
||||
|
||||
private TestFragment mFragment;
|
||||
private Context mContext;
|
||||
@@ -70,6 +81,7 @@ public class WifiCallingSettingsForSubTest {
|
||||
private final PersistableBundle mBundle = new PersistableBundle();
|
||||
|
||||
@Mock private static CarrierConfigManager sCarrierConfigManager;
|
||||
@Mock private CarrierConfigManager mMockConfigManager;
|
||||
@Mock private ImsManager mImsManager;
|
||||
@Mock private TelephonyManager mTelephonyManager;
|
||||
@Mock private PreferenceScreen mPreferenceScreen;
|
||||
@@ -80,6 +92,7 @@ public class WifiCallingSettingsForSubTest {
|
||||
@Mock private ImsConfig mImsConfig;
|
||||
@Mock private ListWithEntrySummaryPreference mButtonWfcMode;
|
||||
@Mock private ListWithEntrySummaryPreference mButtonWfcRoamingMode;
|
||||
@Mock private Preference mUpdateAddress;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -121,6 +134,11 @@ public class WifiCallingSettingsForSubTest {
|
||||
doReturn(mBundle).when(sCarrierConfigManager).getConfigForSubId(anyInt());
|
||||
setDefaultCarrierConfigValues();
|
||||
|
||||
doReturn(sCarrierConfigManager).when(mActivity).getSystemService(
|
||||
CarrierConfigManager.class);
|
||||
doReturn(mContext.getResources()).when(mFragment).getResourcesForSubId();
|
||||
doNothing().when(mFragment).startActivityForResult(any(Intent.class), anyInt());
|
||||
|
||||
mFragment.onAttach(mContext);
|
||||
mFragment.onCreate(null);
|
||||
mFragment.onActivityCreated(null);
|
||||
@@ -131,6 +149,9 @@ public class WifiCallingSettingsForSubTest {
|
||||
CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, false);
|
||||
mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL, true);
|
||||
mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, true);
|
||||
mBundle.putString(
|
||||
CarrierConfigManager.KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING,
|
||||
TEST_EMERGENCY_ADDRESS_CARRIER_APP);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -259,6 +280,61 @@ public class WifiCallingSettingsForSubTest {
|
||||
eq(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onSwitchChanged_enableSetting_shouldLaunchWfcDisclaimerFragment() {
|
||||
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
|
||||
mFragment.onSwitchChanged(null, true);
|
||||
|
||||
// Check the WFC disclaimer fragment is launched.
|
||||
verify(mFragment).startActivityForResult(intentCaptor.capture(),
|
||||
eq(WifiCallingSettingsForSub.REQUEST_CHECK_WFC_DISCLAIMER));
|
||||
Intent intent = intentCaptor.getValue();
|
||||
assertThat(intent.getStringExtra(EXTRA_SHOW_FRAGMENT))
|
||||
.isEqualTo(WifiCallingDisclaimerFragment.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onActivityResult_finishWfcDisclaimerFragment_shouldLaunchCarrierActivity() {
|
||||
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
|
||||
// Emulate the WfcDisclaimerActivity finish.
|
||||
mFragment.onActivityResult(WifiCallingSettingsForSub.REQUEST_CHECK_WFC_DISCLAIMER,
|
||||
Activity.RESULT_OK, null);
|
||||
|
||||
// Check the WFC emergency address activity is launched.
|
||||
verify(mFragment).startActivityForResult(intentCaptor.capture(),
|
||||
eq(WifiCallingSettingsForSub.REQUEST_CHECK_WFC_EMERGENCY_ADDRESS));
|
||||
Intent intent = intentCaptor.getValue();
|
||||
assertEquals(intent.getComponent(), ComponentName.unflattenFromString(
|
||||
TEST_EMERGENCY_ADDRESS_CARRIER_APP));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onActivityResult_finishCarrierActivity_shouldShowWfcPreference() {
|
||||
ReflectionHelpers.setField(mFragment, "mButtonWfcMode", mButtonWfcMode);
|
||||
ReflectionHelpers.setField(mFragment, "mButtonWfcRoamingMode", mButtonWfcRoamingMode);
|
||||
ReflectionHelpers.setField(mFragment, "mUpdateAddress", mUpdateAddress);
|
||||
|
||||
mFragment.onActivityResult(WifiCallingSettingsForSub.REQUEST_CHECK_WFC_EMERGENCY_ADDRESS,
|
||||
Activity.RESULT_OK, null);
|
||||
|
||||
// Check the WFC preferences is added.
|
||||
verify(mPreferenceScreen).addPreference(mButtonWfcMode);
|
||||
verify(mPreferenceScreen).addPreference(mButtonWfcRoamingMode);
|
||||
verify(mPreferenceScreen).addPreference(mUpdateAddress);
|
||||
// Check the WFC enable request.
|
||||
verify(mImsManager).setWfcSetting(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onSwitchChanged_disableSetting_shouldNotLaunchWfcDisclaimerFragment() {
|
||||
mFragment.onSwitchChanged(null, false);
|
||||
|
||||
// Check the WFC disclaimer fragment is not launched.
|
||||
verify(mFragment, never()).startActivityForResult(any(Intent.class), anyInt());
|
||||
}
|
||||
|
||||
protected class TestFragment extends WifiCallingSettingsForSub {
|
||||
@Override
|
||||
protected Object getSystemService(final String name) {
|
||||
|
||||
@@ -22,7 +22,6 @@ import static android.app.slice.SliceItem.FORMAT_TEXT;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
@@ -48,7 +47,6 @@ import androidx.slice.widget.SliceLiveData;
|
||||
import com.android.ims.ImsConfig;
|
||||
import com.android.ims.ImsManager;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.slices.CustomSliceManager;
|
||||
import com.android.settings.slices.CustomSliceRegistry;
|
||||
import com.android.settings.slices.SettingsSliceProvider;
|
||||
import com.android.settings.slices.SliceBroadcastReceiver;
|
||||
@@ -99,9 +97,6 @@ public class WifiCallingSliceHelperTest {
|
||||
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mSlicesFeatureProvider = mFeatureFactory.getSlicesFeatureProvider();
|
||||
CustomSliceManager manager = new CustomSliceManager(mContext);
|
||||
when(mSlicesFeatureProvider.getCustomSliceManager(any(Context.class)))
|
||||
.thenReturn(manager);
|
||||
|
||||
mWfcSliceHelper = new FakeWifiCallingSliceHelper(mContext);
|
||||
|
||||
|
||||
@@ -778,9 +778,9 @@ public class WifiDetailPreferenceControllerTest {
|
||||
|
||||
mockWifiConfig.networkId = 5;
|
||||
when(mockWifiConfig.isPasspoint()).thenReturn(true);
|
||||
spyController.displayPreference(mockScreen);
|
||||
FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, true);
|
||||
|
||||
spyController.displayPreference(mockScreen);
|
||||
mForgetClickListener.getValue().onClick(null);
|
||||
|
||||
verify(mockWifiManager, times(0)).removePasspointConfiguration(mockWifiConfig.FQDN);
|
||||
|
||||
@@ -36,6 +36,8 @@ import androidx.slice.widget.SliceLiveData;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.slices.CustomSliceRegistry;
|
||||
import com.android.settings.slices.SlicesFeatureProviderImpl;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -52,11 +54,15 @@ public class ContextualWifiSliceTest {
|
||||
private ContentResolver mResolver;
|
||||
private WifiManager mWifiManager;
|
||||
private ContextualWifiSlice mWifiSlice;
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mResolver = mock(ContentResolver.class);
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mFeatureFactory.slicesFeatureProvider = new SlicesFeatureProviderImpl();
|
||||
mFeatureFactory.slicesFeatureProvider.newUiSession();
|
||||
doReturn(mResolver).when(mContext).getContentResolver();
|
||||
mWifiManager = mContext.getSystemService(WifiManager.class);
|
||||
|
||||
@@ -65,10 +71,28 @@ public class ContextualWifiSliceTest {
|
||||
mWifiManager.setWifiEnabled(true);
|
||||
|
||||
mWifiSlice = new ContextualWifiSlice(mContext);
|
||||
mWifiSlice.sPreviouslyDisplayed = false;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWifiSlice_hasActiveConnection_shouldReturnNull() {
|
||||
mWifiSlice.sPreviouslyDisplayed = false;
|
||||
final WifiConfiguration config = new WifiConfiguration();
|
||||
config.SSID = "123";
|
||||
mWifiManager.connect(config, null /* listener */);
|
||||
|
||||
final Slice wifiSlice = mWifiSlice.getSlice();
|
||||
|
||||
assertThat(wifiSlice).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWifiSlice_newSession_hasActiveConnection_shouldReturnNull() {
|
||||
// Session: use a non-active value
|
||||
// previous displayed: yes
|
||||
mWifiSlice.sPreviouslyDisplayed = true;
|
||||
mWifiSlice.sActiveUiSession = ~mFeatureFactory.slicesFeatureProvider.getUiSessionToken();
|
||||
|
||||
final WifiConfiguration config = new WifiConfiguration();
|
||||
config.SSID = "123";
|
||||
mWifiManager.connect(config, null /* listener */);
|
||||
@@ -80,7 +104,8 @@ public class ContextualWifiSliceTest {
|
||||
|
||||
@Test
|
||||
public void getWifiSlice_previousDisplayed_hasActiveConnection_shouldHaveTitleAndToggle() {
|
||||
mWifiSlice.mPreviouslyDisplayed = true;
|
||||
mWifiSlice.sActiveUiSession = mFeatureFactory.slicesFeatureProvider.getUiSessionToken();
|
||||
mWifiSlice.sPreviouslyDisplayed = true;
|
||||
final WifiConfiguration config = new WifiConfiguration();
|
||||
config.SSID = "123";
|
||||
mWifiManager.connect(config, null /* listener */);
|
||||
@@ -101,7 +126,8 @@ public class ContextualWifiSliceTest {
|
||||
|
||||
@Test
|
||||
public void getWifiSlice_contextualWifiSlice_shouldReturnContextualWifiSliceUri() {
|
||||
mWifiSlice.mPreviouslyDisplayed = true;
|
||||
mWifiSlice.sActiveUiSession = mFeatureFactory.slicesFeatureProvider.getUiSessionToken();
|
||||
mWifiSlice.sPreviouslyDisplayed = true;
|
||||
|
||||
final Slice wifiSlice = mWifiSlice.getSlice();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user