Snap for 5626642 from 5540373d4f
to qt-c2f2-release
Change-Id: I84e72386d849bd337799cb85a4d464ba0e2d2c1d
This commit is contained in:
@@ -2507,7 +2507,7 @@
|
||||
<intent-filter>
|
||||
<action android:name="com.android.settings.action.SETTINGS"/>
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.order" android:value="-160"/>
|
||||
<meta-data android:name="com.android.settings.order" android:value="-440"/>
|
||||
<meta-data android:name="com.android.settings.category"
|
||||
android:value="com.android.settings.category.ia.apps"/>
|
||||
<meta-data android:name="com.android.settings.summary"
|
||||
|
24
res/drawable/ic_notifications_alert.xml
Normal file
24
res/drawable/ic_notifications_alert.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M18 17v-6c0-3.07-1.63-5.64-4.5-6.32V4c0-0.83-0.67-1.5-1.5-1.5s-1.5 0.67 -1.5 1.5v0.68C7.64 5.36 6 7.92 6 11v6H4v2h16v-2h-2zm-2 0H8v-6c0-2.48 1.51-4.5 4-4.5s4 2.02 4 4.5v6zm-6 3h4c0 1.1-0.9 2-2 2s-2-0.9-2-2zm12-9h-2c0-2.74-1.23-5.19-3.16-6.84l1.41-1.41C20.54 4.77 22 7.71 22 11zM5.75 2.75l1.41 1.41C5.23 5.81 4 8.26 4 11H2c0-3.29 1.46-6.23 3.75-8.25z" />
|
||||
</vector>
|
31
res/drawable/ic_settings_adaptive_sleep.xml
Normal file
31
res/drawable/ic_settings_adaptive_sleep.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
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
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M10.67,21H7v-1h3.13c-0.27-0.63-0.46-1.3-0.56-2H7V6h10v3.5c0.69,0,1.36,0.1,2,0.28V3 c0-1.1-0.9-1.99-2-1.99L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h5.52C11.79,22.45,11.16,21.77,10.67,21z M7,3h10v1H7V3z" />
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M17,12.5c2.48,0,4.5,2.02,4.5,4.5s-2.02,4.5-4.5,4.5s-4.5-2.02-4.5-4.5S14.52,12.5,17,12.5 M17,11 c-3.31,0-6,2.69-6,6s2.69,6,6,6c3.31,0,6-2.69,6-6S20.31,11,17,11L17,11z" />
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M17,14v3l-2.12,2.12C15.42,19.66,16.17,20,17,20c1.66,0,3-1.34,3-3S18.66,14,17,14z" />
|
||||
</vector>
|
@@ -87,11 +87,9 @@
|
||||
|
||||
<com.android.internal.widget.LockPatternView
|
||||
android:id="@+id/lockPattern"
|
||||
android:layout_width="288dp"
|
||||
android:layout_height="288dp"
|
||||
android:layout_marginStart="-42dp"
|
||||
android:layout_marginEnd="-42dp"
|
||||
android:layout_gravity="center_vertical"/>
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
<TextView
|
||||
style="@style/TextAppearance.ErrorText"
|
||||
|
41
res/layout/dialog_mobile_network_color_picker_item.xml
Normal file
41
res/layout/dialog_mobile_network_color_picker_item.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:background="?android:attr/selectableItemBackground" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/color_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/sim_label_padding"
|
||||
android:layout_gravity="center_vertical" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/color_label"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:paddingTop="@dimen/sim_label_padding"
|
||||
android:paddingBottom="@dimen/sim_label_padding"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
|
||||
android:textColor="?android:attr/textColorPrimary"/>
|
||||
|
||||
</LinearLayout>
|
@@ -21,44 +21,89 @@
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/sim_content_padding">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edittext"
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text"
|
||||
android:maxLength="50"
|
||||
android:singleLine="true">
|
||||
<requestFocus/>
|
||||
</EditText>
|
||||
android:paddingEnd="@dimen/sim_content_padding"
|
||||
android:paddingStart="@dimen/sim_content_padding">
|
||||
|
||||
<TextView
|
||||
style="@style/device_info_dialog_label"
|
||||
android:id="@+id/operator_name_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/status_operator"/>
|
||||
<TextView
|
||||
style="@style/device_info_dialog_value"
|
||||
android:id="@+id/operator_name_value"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/device_info_not_available"/>
|
||||
<TextView
|
||||
android:id="@+id/name_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/sim_label_padding"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:text="@string/mobile_network_sim_name_label"/>
|
||||
|
||||
<TextView
|
||||
style="@style/device_info_dialog_label"
|
||||
android:id="@+id/number_label"
|
||||
<EditText
|
||||
android:id="@+id/name_edittext"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text"
|
||||
android:paddingTop="@dimen/sim_label_padding"
|
||||
android:maxLength="50"
|
||||
android:singleLine="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/color_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/sim_label_padding"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:text="@string/mobile_network_sim_color_label"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/color_spinner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/status_number_sim_status"/>
|
||||
<TextView
|
||||
style="@style/device_info_dialog_value"
|
||||
android:id="@+id/number_value"
|
||||
android:layout_marginStart="@dimen/sim_color_spinner_padding"
|
||||
android:layout_marginEnd="@dimen/sim_color_spinner_padding"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/device_info_not_available"/>
|
||||
android:paddingEnd="@dimen/sim_content_padding"
|
||||
android:paddingStart="@dimen/sim_content_padding">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/operator_name_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/sim_label_padding"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:text="@string/status_operator"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/operator_name_value"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/device_info_not_available"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/number_label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/sim_label_padding"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:text="@string/status_number_sim_status"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/number_value"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/device_info_not_available"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
@@ -24,7 +24,7 @@
|
||||
android:padding="@dimen/notification_importance_toggle_marginTop"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
<com.android.settings.notification.NotificationButtonRelativeLayout
|
||||
android:id="@+id/alert"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -33,7 +33,7 @@
|
||||
android:focusable="true">
|
||||
<ImageView
|
||||
android:id="@+id/alert_icon"
|
||||
android:src="@drawable/ic_notifications"
|
||||
android:src="@drawable/ic_notifications_alert"
|
||||
android:background="@android:color/transparent"
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -65,7 +65,7 @@
|
||||
android:layout_below="@id/alert_icon"
|
||||
android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
||||
</com.android.settings.notification.NotificationButtonRelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/silence"
|
||||
|
106
res/layout/preference_radio_with_extra_widget.xml
Normal file
106
res/layout/preference_radio_with_extra_widget.xml
Normal file
@@ -0,0 +1,106 @@
|
||||
<?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
|
||||
-->
|
||||
<!-- This file is copied from preference_radio.xml with modification to
|
||||
support an extra clickable icon on the opposite side horizontally -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@android:id/widget_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:minWidth="56dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/icon_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:minWidth="32dp"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp">
|
||||
<androidx.preference.internal.PreferenceImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
settings:maxWidth="@dimen/secondary_app_icon_size"
|
||||
settings:maxHeight="@dimen/secondary_app_icon_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.TileTitle"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal" />
|
||||
|
||||
<TextView android:id="@android:id/summary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="@style/TextAppearance.Small"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?android:attr/textColorSecondary" />
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/radio_extra_widget_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
<View
|
||||
android:id="@+id/radio_extra_widget_divider"
|
||||
android:layout_width="@dimen/vertical_divider_width"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="36dp"
|
||||
android:layout_marginBottom="36dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="?android:attr/dividerVertical" />
|
||||
<ImageView
|
||||
android:id="@+id/radio_extra_widget"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:src="@drawable/ic_settings_about"
|
||||
android:contentDescription="@string/information_label"
|
||||
android:layout_gravity="center"
|
||||
android:background="?android:attr/selectableItemBackground" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
Binary file not shown.
@@ -31,6 +31,10 @@
|
||||
|
||||
<style name="Theme.SubSettings" parent="Theme.SubSettings.Base"/>
|
||||
|
||||
<style name="ThemeOverlay.SwitchBar.Settings" parent="ThemeOverlay.SwitchBar.Settings.Base">
|
||||
<item name="android:textColorPrimaryInverse">@android:color/black</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.AlertDialog.Base" parent="@style/Theme.AppCompat.DayNight.Dialog.Alert">
|
||||
<item name="colorAccent">@*android:color/accent_device_default_dark</item>
|
||||
<item name="android:colorBackground">@color/dialog_background</item>
|
||||
|
@@ -166,6 +166,7 @@
|
||||
<dimen name="sim_dialog_margin_bottom">16dip</dimen>
|
||||
<!-- SIM Dialog padding -->
|
||||
<dimen name="sim_dialog_padding">8dip</dimen>
|
||||
<dimen name="sim_color_spinner_padding">12dip</dimen>
|
||||
<dimen name="sim_label_padding">16dip</dimen>
|
||||
<dimen name="sim_content_padding">24dip</dimen>
|
||||
<!-- Sim Card Name length -->
|
||||
|
@@ -2833,7 +2833,7 @@
|
||||
<!-- Setting option summary when adaptive sleep is off [CHAR LIMIT=NONE] -->
|
||||
<string name="adaptive_sleep_summary_off">Off</string>
|
||||
<!-- Description about the feature adaptive sleep [CHAR LIMIT=NONE]-->
|
||||
<string name="adaptive_sleep_description">Prevents your screen from turning off if you’re looking at it.</string>
|
||||
<string name="adaptive_sleep_description">Keep screen on when viewing it</string>
|
||||
<!-- Description feature's privacy sensitive details to make sure users understand what feature users, what it saves/sends etc [CHAR LIMIT=NONE]-->
|
||||
<string name="adaptive_sleep_privacy">Screen attention uses the front camera to see if someone is looking at the screen. It works on device, and images are never stored or sent to Google.</string>
|
||||
|
||||
@@ -10208,7 +10208,7 @@
|
||||
<!-- Message for the alert dialog which says that the current default home app does not support gesture navigation. [CHAR LIMIT=NONE] -->
|
||||
<string name="gesture_not_supported_dialog_message">Not supported by your default home app, <xliff:g id="default_home_app" example="Pixel Launcher">%s</xliff:g></string>
|
||||
|
||||
<!-- Positive button for the alert dialog when gesture nav not supported by launcher [CHAR LIMIT=40] -->
|
||||
<!-- Positive button for the alert dialog when gesture nav not supported by launcher [CHAR LIMIT=60] -->
|
||||
<string name="gesture_not_supported_positive_button">Switch default home app</string>
|
||||
|
||||
<!-- Content description for the Information icon [CHAR LIMIT=30] -->
|
||||
@@ -10961,10 +10961,14 @@
|
||||
subscription in various places in the Settings app. The default name is typically just the
|
||||
carrier name, but especially in multi-SIM configurations users may want to use a different
|
||||
name. [CHAR LIMIT=40] -->
|
||||
<string name="mobile_network_sim_name">SIM name</string>
|
||||
<!-- Label on the confirmation button of a dialog that lets a user set the display name of a
|
||||
mobile network subscription [CHAR LIMIT=20] -->
|
||||
<string name="mobile_network_sim_name_rename">Rename</string>
|
||||
<string name="mobile_network_sim_name">SIM name & color</string>
|
||||
<!-- Label for an item listing the name of the SIM that the user has specified. [CHAR LIMIT=40] -->
|
||||
<string name="mobile_network_sim_name_label">Name</string>
|
||||
<!-- Label for an item listing the color of the SIM that the user has specified. [CHAR LIMIT=40] -->
|
||||
<string name="mobile_network_sim_color_label">Color (used by compatible apps)</string>
|
||||
<!-- Label on the confirmation button of a dialog that lets a user set the display name and
|
||||
color of a mobile network subscription [CHAR LIMIT=20] -->
|
||||
<string name="mobile_network_sim_name_rename">Save</string>
|
||||
<!-- Label for the on position of a switch on the mobile network details page which allows
|
||||
disabling/enabling a SIM. The SIM is enabled in this state. [CHAR LIMIT=40] -->
|
||||
<string name="mobile_network_use_sim_on">Use SIM</string>
|
||||
|
@@ -90,7 +90,7 @@
|
||||
<item name="android:backgroundDimEnabled">false</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.SwitchBar.Settings" parent="@*android:style/ThemeOverlay.DeviceDefault.ActionBar">
|
||||
<style name="ThemeOverlay.SwitchBar.Settings.Base" parent="@*android:style/ThemeOverlay.DeviceDefault.ActionBar">
|
||||
<item name="android:elevation">1dp</item>
|
||||
<item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
|
||||
<item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
|
||||
@@ -99,6 +99,8 @@
|
||||
<item name="switchBarRestrictionIcon">@*android:drawable/ic_info</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay.SwitchBar.Settings" parent="ThemeOverlay.SwitchBar.Settings.Base"/>
|
||||
|
||||
<style name="Widget.SwitchBar.Switch" parent="@android:style/Widget.Material.CompoundButton.Switch">
|
||||
<item name="android:trackTint">@color/switchbar_switch_track_tint</item>
|
||||
<item name="android:thumbTint">@color/switchbar_switch_thumb_tint</item>
|
||||
|
@@ -25,6 +25,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
@@ -65,7 +66,7 @@ public class FallbackHome extends Activity {
|
||||
@Override
|
||||
public void onColorsChanged(WallpaperColors colors, int which) {
|
||||
if (colors != null) {
|
||||
View decorView = getWindow().getDecorView();
|
||||
final View decorView = getWindow().getDecorView();
|
||||
decorView.setSystemUiVisibility(
|
||||
updateVisibilityFlagsFromColors(colors, decorView.getSystemUiVisibility()));
|
||||
mWallManager.removeOnColorsChangedListener(this);
|
||||
@@ -81,7 +82,7 @@ public class FallbackHome extends Activity {
|
||||
// we don't flash the wallpaper before SUW
|
||||
mProvisioned = Settings.Global.getInt(getContentResolver(),
|
||||
Settings.Global.DEVICE_PROVISIONED, 0) != 0;
|
||||
int flags;
|
||||
final int flags;
|
||||
if (!mProvisioned) {
|
||||
setTheme(R.style.FallbackHome_SetupWizard);
|
||||
flags = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
@@ -91,18 +92,11 @@ public class FallbackHome extends Activity {
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
|
||||
}
|
||||
|
||||
// Set the system ui flags to light status bar if the wallpaper supports dark text to match
|
||||
// current system ui color tints. Use a listener to wait for colors if not ready yet.
|
||||
mWallManager = getSystemService(WallpaperManager.class);
|
||||
if (mWallManager == null) {
|
||||
Log.w(TAG, "Wallpaper manager isn't ready, can't listen to color changes!");
|
||||
} else {
|
||||
WallpaperColors colors = mWallManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
|
||||
if (colors == null) {
|
||||
mWallManager.addOnColorsChangedListener(mColorsChangedListener, null /* handler */);
|
||||
} else {
|
||||
flags = updateVisibilityFlagsFromColors(colors, flags);
|
||||
}
|
||||
loadWallpaperColors(flags);
|
||||
}
|
||||
getWindow().getDecorView().setSystemUiVisibility(flags);
|
||||
|
||||
@@ -139,6 +133,33 @@ public class FallbackHome extends Activity {
|
||||
}
|
||||
};
|
||||
|
||||
private void loadWallpaperColors(int flags) {
|
||||
final AsyncTask loadWallpaperColorsTask = new AsyncTask<Object, Void, Integer>() {
|
||||
@Override
|
||||
protected Integer doInBackground(Object... params) {
|
||||
final WallpaperColors colors =
|
||||
mWallManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
|
||||
|
||||
// Use a listener to wait for colors if not ready yet.
|
||||
if (colors == null) {
|
||||
mWallManager.addOnColorsChangedListener(mColorsChangedListener,
|
||||
null /* handler */);
|
||||
return null;
|
||||
}
|
||||
return updateVisibilityFlagsFromColors(colors, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Integer flagsToUpdate) {
|
||||
if (flagsToUpdate == null) {
|
||||
return;
|
||||
}
|
||||
getWindow().getDecorView().setSystemUiVisibility(flagsToUpdate);
|
||||
}
|
||||
};
|
||||
loadWallpaperColorsTask.execute();
|
||||
}
|
||||
|
||||
private void maybeFinish() {
|
||||
if (getSystemService(UserManager.class).isUserUnlocked()) {
|
||||
final Intent homeIntent = new Intent(Intent.ACTION_MAIN)
|
||||
@@ -162,6 +183,8 @@ public class FallbackHome extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
// Set the system ui flags to light status bar if the wallpaper supports dark text to match
|
||||
// current system ui color tints.
|
||||
private int updateVisibilityFlagsFromColors(WallpaperColors colors, int flags) {
|
||||
if ((colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0) {
|
||||
return flags | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
|
||||
|
@@ -25,9 +25,9 @@ import com.android.settings.core.TogglePreferenceController;
|
||||
|
||||
|
||||
public class AdaptiveSleepPreferenceController extends TogglePreferenceController {
|
||||
|
||||
private final String SYSTEM_KEY = ADAPTIVE_SLEEP;
|
||||
private final int DEFAULT_VALUE = 0;
|
||||
public static final String PREF_NAME = "adaptive_sleep";
|
||||
private static final String SYSTEM_KEY = ADAPTIVE_SLEEP;
|
||||
private static final int DEFAULT_VALUE = 0;
|
||||
|
||||
final boolean hasSufficientPermissions;
|
||||
|
||||
@@ -35,9 +35,7 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
|
||||
super(context, key);
|
||||
|
||||
final PackageManager packageManager = mContext.getPackageManager();
|
||||
final String attentionPackage = packageManager.getAttentionServicePackageName();
|
||||
hasSufficientPermissions = attentionPackage != null && packageManager.checkPermission(
|
||||
Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED;
|
||||
hasSufficientPermissions = hasSufficientPermission(packageManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -46,7 +44,6 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
|
||||
SYSTEM_KEY, DEFAULT_VALUE) != DEFAULT_VALUE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean setChecked(boolean isChecked) {
|
||||
Settings.System.putInt(mContext.getContentResolver(), SYSTEM_KEY,
|
||||
@@ -57,10 +54,7 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
|
||||
@Override
|
||||
@AvailabilityStatus
|
||||
public int getAvailabilityStatus() {
|
||||
return mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_adaptive_sleep_available)
|
||||
? AVAILABLE_UNSEARCHABLE
|
||||
: UNSUPPORTED_ON_DEVICE;
|
||||
return isControllerAvailable(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,4 +63,17 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
|
||||
? R.string.adaptive_sleep_summary_on
|
||||
: R.string.adaptive_sleep_summary_off);
|
||||
}
|
||||
|
||||
public static int isControllerAvailable(Context context) {
|
||||
return context.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_adaptive_sleep_available)
|
||||
? AVAILABLE_UNSEARCHABLE
|
||||
: UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
private static boolean hasSufficientPermission(PackageManager packageManager) {
|
||||
final String attentionPackage = packageManager.getAttentionServicePackageName();
|
||||
return attentionPackage != null && packageManager.checkPermission(
|
||||
Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
}
|
||||
|
@@ -16,10 +16,15 @@
|
||||
|
||||
package com.android.settings.display;
|
||||
|
||||
import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF;
|
||||
import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF_KEY_INTERACTED;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
@@ -40,8 +45,15 @@ public class AdaptiveSleepSettings extends DashboardFragment {
|
||||
super.onCreate(icicle);
|
||||
final FooterPreference footerPreference =
|
||||
mFooterPreferenceMixin.createFooterPreference();
|
||||
final Context context = getContext();
|
||||
|
||||
footerPreference.setIcon(R.drawable.ic_privacy_shield_24dp);
|
||||
footerPreference.setTitle(R.string.adaptive_sleep_privacy);
|
||||
|
||||
context.getSharedPreferences(PREF, Context.MODE_PRIVATE)
|
||||
.edit()
|
||||
.putBoolean(PREF_KEY_INTERACTED, true)
|
||||
.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -352,15 +352,10 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
|
||||
|
||||
@VisibleForTesting
|
||||
boolean shouldHideSipper(BatterySipper sipper) {
|
||||
// Don't show hidden system module
|
||||
final String packageName = mBatteryUtils.getPackageName(sipper.getUid());
|
||||
if (!TextUtils.isEmpty(packageName)
|
||||
&& AppUtils.isHiddenSystemModule(mContext, packageName)) {
|
||||
return true;
|
||||
}
|
||||
// Don't show over-counted and unaccounted in any condition
|
||||
// Don't show over-counted, unaccounted and hidden system module in any condition
|
||||
return sipper.drainType == BatterySipper.DrainType.OVERCOUNTED
|
||||
|| sipper.drainType == BatterySipper.DrainType.UNACCOUNTED;
|
||||
|| sipper.drainType == BatterySipper.DrainType.UNACCOUNTED
|
||||
|| mBatteryUtils.isHiddenSystemModule(sipper);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
@@ -47,6 +47,7 @@ import com.android.settings.fuelgauge.batterytip.AnomalyInfo;
|
||||
import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
|
||||
import com.android.settings.fuelgauge.batterytip.StatsManagerConfig;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.applications.AppUtils;
|
||||
import com.android.settingslib.fuelgauge.Estimate;
|
||||
import com.android.settingslib.fuelgauge.EstimateKt;
|
||||
import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
|
||||
@@ -189,8 +190,10 @@ public class BatteryUtils {
|
||||
&& sipper.drainType != BatterySipper.DrainType.UNACCOUNTED
|
||||
&& sipper.drainType != BatterySipper.DrainType.BLUETOOTH
|
||||
&& sipper.drainType != BatterySipper.DrainType.WIFI
|
||||
&& sipper.drainType != BatterySipper.DrainType.IDLE) {
|
||||
// Don't add it if it is overcounted, unaccounted, wifi, bluetooth, or screen
|
||||
&& sipper.drainType != BatterySipper.DrainType.IDLE
|
||||
&& !isHiddenSystemModule(sipper)) {
|
||||
// Don't add it if it is overcounted, unaccounted, wifi, bluetooth, screen
|
||||
// or hidden system modules
|
||||
proportionalSmearPowerMah += sipper.totalPowerMah;
|
||||
}
|
||||
}
|
||||
@@ -253,7 +256,27 @@ public class BatteryUtils {
|
||||
|| drainType == BatterySipper.DrainType.WIFI
|
||||
|| (sipper.totalPowerMah * SECONDS_IN_HOUR) < MIN_POWER_THRESHOLD_MILLI_AMP
|
||||
|| mPowerUsageFeatureProvider.isTypeService(sipper)
|
||||
|| mPowerUsageFeatureProvider.isTypeSystem(sipper);
|
||||
|| mPowerUsageFeatureProvider.isTypeSystem(sipper)
|
||||
|| isHiddenSystemModule(sipper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@code true} if one of packages in {@code sipper} is hidden system modules
|
||||
*/
|
||||
public boolean isHiddenSystemModule(BatterySipper sipper) {
|
||||
if (sipper.uidObj == null) {
|
||||
return false;
|
||||
}
|
||||
sipper.mPackages = mPackageManager.getPackagesForUid(sipper.getUid());
|
||||
if (sipper.mPackages != null) {
|
||||
for (int i = 0, length = sipper.mPackages.length; i < length; i++) {
|
||||
if (AppUtils.isHiddenSystemModule(mContext, sipper.mPackages[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -20,7 +20,6 @@ import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.BatteryStats;
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
@@ -72,22 +71,33 @@ public class HighUsageDetector implements BatteryTipDetector {
|
||||
if (mPolicy.highUsageEnabled && mDischarging) {
|
||||
parseBatteryData();
|
||||
if (mDataParser.isDeviceHeavilyUsed() || mPolicy.testHighUsageTip) {
|
||||
final List<BatterySipper> batterySippers = mBatteryStatsHelper.getUsageList();
|
||||
for (int i = 0, size = batterySippers.size(); i < size; i++) {
|
||||
final BatterySipper batterySipper = batterySippers.get(i);
|
||||
if (!mBatteryUtils.shouldHideSipper(batterySipper)) {
|
||||
final long foregroundTimeMs = mBatteryUtils.getProcessTimeMs(
|
||||
BatteryUtils.StatusType.FOREGROUND, batterySipper.uidObj,
|
||||
BatteryStats.STATS_SINCE_CHARGED);
|
||||
if (foregroundTimeMs >= DateUtils.MINUTE_IN_MILLIS) {
|
||||
mHighUsageAppList.add(new AppInfo.Builder()
|
||||
.setUid(batterySipper.getUid())
|
||||
.setPackageName(
|
||||
mBatteryUtils.getPackageName(batterySipper.getUid()))
|
||||
.setScreenOnTimeMs(foregroundTimeMs)
|
||||
.build());
|
||||
}
|
||||
final BatteryStats batteryStats = mBatteryStatsHelper.getStats();
|
||||
final List<BatterySipper> batterySippers
|
||||
= new ArrayList<>(mBatteryStatsHelper.getUsageList());
|
||||
final double totalPower = mBatteryStatsHelper.getTotalPower();
|
||||
final int dischargeAmount = batteryStats != null
|
||||
? batteryStats.getDischargeAmount(BatteryStats.STATS_SINCE_CHARGED)
|
||||
: 0;
|
||||
|
||||
Collections.sort(batterySippers,
|
||||
(sipper1, sipper2) -> Double.compare(sipper2.totalSmearedPowerMah,
|
||||
sipper1.totalSmearedPowerMah));
|
||||
for (BatterySipper batterySipper : batterySippers) {
|
||||
final double percent = mBatteryUtils.calculateBatteryPercent(
|
||||
batterySipper.totalSmearedPowerMah, totalPower, 0, dischargeAmount);
|
||||
if ((percent + 0.5f < 1f) || mBatteryUtils.shouldHideSipper(batterySipper)) {
|
||||
// Don't show it if we should hide or usage percentage is lower than 1%
|
||||
continue;
|
||||
}
|
||||
mHighUsageAppList.add(new AppInfo.Builder()
|
||||
.setUid(batterySipper.getUid())
|
||||
.setPackageName(
|
||||
mBatteryUtils.getPackageName(batterySipper.getUid()))
|
||||
.build());
|
||||
if (mHighUsageAppList.size() >= mPolicy.highUsageAppCount) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// When in test mode, add an app if necessary
|
||||
@@ -97,10 +107,6 @@ public class HighUsageDetector implements BatteryTipDetector {
|
||||
.setScreenOnTimeMs(TimeUnit.HOURS.toMillis(3))
|
||||
.build());
|
||||
}
|
||||
|
||||
Collections.sort(mHighUsageAppList, Collections.reverseOrder());
|
||||
mHighUsageAppList = mHighUsageAppList.subList(0,
|
||||
Math.min(mPolicy.highUsageAppCount, mHighUsageAppList.size()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,10 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVE
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
|
||||
|
||||
import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_GONE;
|
||||
import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_INFO;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
@@ -29,7 +33,6 @@ import android.graphics.drawable.Drawable;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
@@ -41,6 +44,7 @@ import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settings.widget.RadioButtonPickerFragment;
|
||||
import com.android.settings.widget.RadioButtonPreference;
|
||||
import com.android.settings.widget.RadioButtonPreferenceWithExtraWidget;
|
||||
import com.android.settings.widget.VideoPreference;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
import com.android.settingslib.widget.CandidateInfo;
|
||||
@@ -94,8 +98,25 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addStaticPreferences(PreferenceScreen screen) {
|
||||
public void updateCandidates() {
|
||||
final String defaultKey = getDefaultKey();
|
||||
final String systemDefaultKey = getSystemDefaultKey();
|
||||
final PreferenceScreen screen = getPreferenceScreen();
|
||||
screen.removeAll();
|
||||
screen.addPreference(mVideoPreference);
|
||||
|
||||
final List<? extends CandidateInfo> candidateList = getCandidates();
|
||||
if (candidateList == null) {
|
||||
return;
|
||||
}
|
||||
for (CandidateInfo info : candidateList) {
|
||||
RadioButtonPreferenceWithExtraWidget pref =
|
||||
new RadioButtonPreferenceWithExtraWidget(getPrefContext());
|
||||
bindPreference(pref, info.getKey(), info, defaultKey);
|
||||
bindPreferenceExtra(pref, info.getKey(), info, defaultKey, systemDefaultKey);
|
||||
screen.addPreference(pref);
|
||||
}
|
||||
mayCheckOnlyRadioButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -135,6 +156,13 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment {
|
||||
|
||||
@Override
|
||||
protected boolean setDefaultKey(String key) {
|
||||
final Context c = getContext();
|
||||
if (key == KEY_SYSTEM_NAV_GESTURAL &&
|
||||
!SystemNavigationPreferenceController.isGestureNavSupportedByDefaultLauncher(c)) {
|
||||
// This should not happen since the preference is disabled. Return to be safe.
|
||||
return false;
|
||||
}
|
||||
|
||||
setCurrentSystemNavigationMode(mOverlayManager, key);
|
||||
setIllustrationVideo(mVideoPreference, key);
|
||||
return true;
|
||||
@@ -196,10 +224,36 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment {
|
||||
@Override
|
||||
public void bindPreferenceExtra(RadioButtonPreference pref,
|
||||
String key, CandidateInfo info, String defaultKey, String systemDefaultKey) {
|
||||
if (info instanceof NavModeCandidateInfo) {
|
||||
pref.setSummary(((NavModeCandidateInfo) info).loadSummary());
|
||||
pref.setAppendixVisibility(View.GONE);
|
||||
if (!(info instanceof NavModeCandidateInfo)
|
||||
|| !(pref instanceof RadioButtonPreferenceWithExtraWidget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pref.setSummary(((NavModeCandidateInfo) info).loadSummary());
|
||||
|
||||
RadioButtonPreferenceWithExtraWidget p = (RadioButtonPreferenceWithExtraWidget) pref;
|
||||
if (info.getKey() == KEY_SYSTEM_NAV_GESTURAL
|
||||
&& !SystemNavigationPreferenceController.isGestureNavSupportedByDefaultLauncher(
|
||||
getContext())) {
|
||||
p.setEnabled(false);
|
||||
p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_INFO);
|
||||
p.setExtraWidgetOnClickListener((v) -> {
|
||||
showGestureNavDisabledDialog();
|
||||
});
|
||||
} else {
|
||||
p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void showGestureNavDisabledDialog() {
|
||||
final String defaultHomeAppName = SystemNavigationPreferenceController
|
||||
.getDefaultHomeAppName(getContext());
|
||||
final String message = getString(R.string.gesture_not_supported_dialog_message,
|
||||
defaultHomeAppName);
|
||||
AlertDialog d = new AlertDialog.Builder(getContext())
|
||||
.setMessage(message)
|
||||
.setPositiveButton(R.string.okay, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
static class NavModeCandidateInfo extends CandidateInfo {
|
||||
|
@@ -22,11 +22,14 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SystemNavigationPreferenceController extends BasePreferenceController {
|
||||
|
||||
static final String PREF_KEY_SYSTEM_NAVIGATION = "gesture_system_navigation";
|
||||
@@ -98,4 +101,31 @@ public class SystemNavigationPreferenceController extends BasePreferenceControll
|
||||
return NAV_BAR_MODE_GESTURAL == context.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_navBarInteractionMode);
|
||||
}
|
||||
|
||||
static boolean isGestureNavSupportedByDefaultLauncher(Context context) {
|
||||
final ComponentName cn = context.getPackageManager().getHomeActivities(new ArrayList<>());
|
||||
if (cn == null) {
|
||||
// There is no default home app set for the current user, don't make any changes yet.
|
||||
return true;
|
||||
}
|
||||
ComponentName recentsComponentName = ComponentName.unflattenFromString(context.getString(
|
||||
com.android.internal.R.string.config_recentsComponentName));
|
||||
return recentsComponentName.getPackageName().equals(cn.getPackageName());
|
||||
}
|
||||
|
||||
static String getDefaultHomeAppName(Context context) {
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
final ComponentName cn = pm.getHomeActivities(new ArrayList<>());
|
||||
if (cn != null) {
|
||||
try {
|
||||
ApplicationInfo ai = pm.getApplicationInfo(cn.getPackageName(), 0);
|
||||
if (ai != null) {
|
||||
return pm.getApplicationLabel(ai).toString();
|
||||
}
|
||||
} catch (final PackageManager.NameNotFoundException e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
@@ -64,12 +64,21 @@ public class SettingsContextualCardProvider extends ContextualCardProvider {
|
||||
.setCardName(contextualNotificationChannelSliceUri)
|
||||
.setCardCategory(ContextualCard.Category.POSSIBLE)
|
||||
.build();
|
||||
final String contextualAdaptiveSleepSliceUri =
|
||||
CustomSliceRegistry.CONTEXTUAL_ADAPTIVE_SLEEP_URI.toString();
|
||||
final ContextualCard contextualAdaptiveSleepCard =
|
||||
ContextualCard.newBuilder()
|
||||
.setSliceUri(contextualAdaptiveSleepSliceUri)
|
||||
.setCardName(contextualAdaptiveSleepSliceUri)
|
||||
.setCardCategory(ContextualCard.Category.DEFAULT)
|
||||
.build();
|
||||
final ContextualCardList cards = ContextualCardList.newBuilder()
|
||||
.addCard(wifiCard)
|
||||
.addCard(connectedDeviceCard)
|
||||
.addCard(lowStorageCard)
|
||||
.addCard(batteryFixCard)
|
||||
.addCard(notificationChannelCard)
|
||||
.addCard(contextualAdaptiveSleepCard)
|
||||
.build();
|
||||
|
||||
return cards;
|
||||
|
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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.homepage.contextualcards.slices;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.display.AdaptiveSleepPreferenceController.PREF_NAME;
|
||||
import static com.android.settings.display.AdaptiveSleepPreferenceController.isControllerAvailable;
|
||||
import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_ADAPTIVE_SLEEP_URI;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.display.AdaptiveSleepSettings;
|
||||
import com.android.settings.slices.CustomSliceable;
|
||||
import com.android.settings.slices.SliceBuilderUtils;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ContextualAdaptiveSleepSlice implements CustomSliceable {
|
||||
private static final String TAG = "ContextualAdaptiveSleepSlice";
|
||||
private static final long DEFAULT_SETUP_TIME = 0;
|
||||
private Context mContext;
|
||||
|
||||
@VisibleForTesting
|
||||
static final long DEFERRED_TIME_DAYS = TimeUnit.DAYS.toMillis(14);
|
||||
@VisibleForTesting
|
||||
static final String PREF_KEY_SETUP_TIME = "adaptive_sleep_setup_time";
|
||||
|
||||
public static final String PREF_KEY_INTERACTED = "adaptive_sleep_interacted";
|
||||
public static final String PREF = "adaptive_sleep_slice";
|
||||
|
||||
public ContextualAdaptiveSleepSlice(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice getSlice() {
|
||||
final long setupTime = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE).getLong(
|
||||
PREF_KEY_SETUP_TIME, DEFAULT_SETUP_TIME);
|
||||
if (setupTime == DEFAULT_SETUP_TIME) {
|
||||
// Set the first setup time.
|
||||
mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE)
|
||||
.edit()
|
||||
.putLong(PREF_KEY_SETUP_TIME, System.currentTimeMillis())
|
||||
.apply();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Display the contextual card only if all the following 3 conditions hold:
|
||||
// 1. The Screen Attention is enabled in Settings.
|
||||
// 2. The device is not recently set up.
|
||||
// 3. Current user hasn't opened Screen Attention's settings page before.
|
||||
if (isSettingsAvailable() && !isUserInteracted() && !isRecentlySetup()) {
|
||||
final IconCompat icon = IconCompat.createWithResource(mContext,
|
||||
R.drawable.ic_settings_adaptive_sleep);
|
||||
final CharSequence title = mContext.getText(R.string.adaptive_sleep_title);
|
||||
final CharSequence subtitle = mContext.getText(R.string.adaptive_sleep_description);
|
||||
|
||||
final SliceAction pAction = SliceAction.createDeeplink(getPrimaryAction(),
|
||||
icon,
|
||||
ListBuilder.ICON_IMAGE,
|
||||
title);
|
||||
final ListBuilder listBuilder = new ListBuilder(mContext,
|
||||
CONTEXTUAL_ADAPTIVE_SLEEP_URI,
|
||||
ListBuilder.INFINITY)
|
||||
.addRow(new ListBuilder.RowBuilder()
|
||||
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
|
||||
.setTitle(title)
|
||||
.setSubtitle(subtitle)
|
||||
.setPrimaryAction(pAction));
|
||||
return listBuilder.build();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getUri() {
|
||||
return CONTEXTUAL_ADAPTIVE_SLEEP_URI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
final CharSequence screenTitle = mContext.getText(R.string.adaptive_sleep_title);
|
||||
final Uri contentUri = new Uri.Builder().appendPath(PREF_NAME).build();
|
||||
return SliceBuilderUtils.buildSearchResultPageIntent(mContext,
|
||||
AdaptiveSleepSettings.class.getName(), PREF_NAME, screenTitle.toString(),
|
||||
SettingsEnums.SLICE).setClassName(mContext.getPackageName(),
|
||||
SubSettings.class.getName()).setData(contentUri);
|
||||
}
|
||||
|
||||
private PendingIntent getPrimaryAction() {
|
||||
final Intent intent = getIntent();
|
||||
return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the current user has opened the Screen Attention settings page
|
||||
* before, otherwise {@code false}.
|
||||
*/
|
||||
private boolean isUserInteracted() {
|
||||
return mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE).getBoolean(
|
||||
PREF_KEY_INTERACTED, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The device is recently set up means its first settings-open time is within 2 weeks ago.
|
||||
*
|
||||
* @return {@code true} if the device is recently set up, otherwise {@code false}.
|
||||
*/
|
||||
private boolean isRecentlySetup() {
|
||||
final long endTime = System.currentTimeMillis() - DEFERRED_TIME_DAYS;
|
||||
final long firstSetupTime = mContext.getSharedPreferences(PREF,
|
||||
Context.MODE_PRIVATE).getLong(PREF_KEY_SETUP_TIME, DEFAULT_SETUP_TIME);
|
||||
return firstSetupTime > endTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the screen attention settings is enabled. Contextual card will only appear
|
||||
* when the screen attention settings is available.
|
||||
*
|
||||
* @return {@code true} if screen attention settings is enabled, otherwise {@code false}
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean isSettingsAvailable() {
|
||||
return isControllerAvailable(mContext) == AVAILABLE;
|
||||
}
|
||||
}
|
@@ -18,6 +18,7 @@ package com.android.settings.network;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.UserManager;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.settings.R;
|
||||
@@ -66,5 +67,10 @@ public class MobileNetworkListFragment extends DashboardFragment {
|
||||
result.add(sir);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPageSearchEnabled(Context context) {
|
||||
return context.getSystemService(UserManager.class).isAdminUser();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -277,5 +277,11 @@ public class MobileNetworkSettings extends RestrictedDashboardFragment {
|
||||
result.add(sir);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** suppress full page if user is not admin */
|
||||
@Override
|
||||
protected boolean isPageSearchEnabled(Context context) {
|
||||
return context.getSystemService(UserManager.class).isAdminUser();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -19,6 +19,10 @@ package com.android.settings.network.telephony;
|
||||
import android.app.Dialog;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.ShapeDrawable;
|
||||
import android.graphics.drawable.shapes.OvalShape;
|
||||
import android.os.Bundle;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
@@ -30,7 +34,12 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settings.R;
|
||||
@@ -42,9 +51,12 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
/** A dialog allowing the display name of a mobile network subscription to be changed */
|
||||
/**
|
||||
* A dialog allowing the display name of a mobile network subscription to be changed
|
||||
*/
|
||||
public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragment {
|
||||
public static final String TAG ="RenameMobileNetwork";
|
||||
|
||||
public static final String TAG = "RenameMobileNetwork";
|
||||
|
||||
private static final String KEY_SUBSCRIPTION_ID = "subscription_id";
|
||||
|
||||
@@ -52,6 +64,8 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
private int mSubId;
|
||||
private EditText mNameView;
|
||||
private Spinner mColorSpinner;
|
||||
private Color[] mColors;
|
||||
|
||||
public static RenameMobileNetworkDialogFragment newInstance(int subscriptionId) {
|
||||
final Bundle args = new Bundle(1);
|
||||
@@ -76,6 +90,11 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen
|
||||
return mNameView;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected Spinner getColorSpinnerView() {
|
||||
return mColorSpinner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
@@ -87,6 +106,8 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||
mColors = getColors();
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
final LayoutInflater layoutInflater = builder.getContext().getSystemService(
|
||||
LayoutInflater.class);
|
||||
@@ -95,9 +116,11 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen
|
||||
builder.setTitle(R.string.mobile_network_sim_name)
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.mobile_network_sim_name_rename, (dialog, which) -> {
|
||||
String newName = mNameView.getText().toString();
|
||||
mSubscriptionManager.setDisplayName(newName, mSubId,
|
||||
mSubscriptionManager.setDisplayName(mNameView.getText().toString(), mSubId,
|
||||
SubscriptionManager.NAME_SOURCE_USER_INPUT);
|
||||
mSubscriptionManager.setIconTint(
|
||||
mColors[mColorSpinner.getSelectedItemPosition()].getColor(),
|
||||
mSubId);
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null);
|
||||
return builder.create();
|
||||
@@ -105,7 +128,7 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen
|
||||
|
||||
@VisibleForTesting
|
||||
protected void populateView(View view) {
|
||||
mNameView = view.findViewById(R.id.edittext);
|
||||
mNameView = view.findViewById(R.id.name_edittext);
|
||||
final SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(mSubId);
|
||||
if (info == null) {
|
||||
Log.w(TAG, "got null SubscriptionInfo for mSubId:" + mSubId);
|
||||
@@ -117,6 +140,17 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen
|
||||
mNameView.setSelection(displayName.length());
|
||||
}
|
||||
|
||||
mColorSpinner = view.findViewById(R.id.color_spinner);
|
||||
final ColorAdapter adapter = new ColorAdapter(getContext(),
|
||||
R.layout.dialog_mobile_network_color_picker_item, mColors);
|
||||
mColorSpinner.setAdapter(adapter);
|
||||
for (int i = 0; i < mColors.length; i++) {
|
||||
if (mColors[i].getColor() == info.getIconTint()) {
|
||||
mColorSpinner.setSelection(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final TextView operatorName = view.findViewById(R.id.operator_name_value);
|
||||
final ServiceState serviceState = mTelephonyManager.getServiceStateForSubscriber(mSubId);
|
||||
operatorName.setText(serviceState.getOperatorAlphaLong());
|
||||
@@ -134,4 +168,80 @@ public class RenameMobileNetworkDialogFragment extends InstrumentedDialogFragmen
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.MOBILE_NETWORK_RENAME_DIALOG;
|
||||
}
|
||||
|
||||
private class ColorAdapter extends ArrayAdapter<Color> {
|
||||
|
||||
private Context mContext;
|
||||
private int mItemResId;
|
||||
|
||||
public ColorAdapter(Context context, int resource, Color[] colors) {
|
||||
super(context, resource, colors);
|
||||
mContext = context;
|
||||
mItemResId = resource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
final LayoutInflater inflater = (LayoutInflater)
|
||||
mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
if (convertView == null) {
|
||||
convertView = inflater.inflate(mItemResId, null);
|
||||
}
|
||||
((ImageView) convertView.findViewById(R.id.color_icon))
|
||||
.setImageDrawable(getItem(position).getDrawable());
|
||||
((TextView) convertView.findViewById(R.id.color_label))
|
||||
.setText(getItem(position).getLabel());
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getDropDownView(int position, View convertView, ViewGroup parent) {
|
||||
return getView(position, convertView, parent);
|
||||
}
|
||||
}
|
||||
|
||||
private Color[] getColors() {
|
||||
final Resources res = getContext().getResources();
|
||||
final int[] colorInts = res.getIntArray(com.android.internal.R.array.sim_colors);
|
||||
final String[] colorStrings = res.getStringArray(R.array.color_picker);
|
||||
final int iconSize = res.getDimensionPixelSize(R.dimen.color_swatch_size);
|
||||
final int strokeWidth = res.getDimensionPixelSize(R.dimen.color_swatch_stroke_width);
|
||||
final Color[] colors = new Color[colorInts.length];
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
colors[i] = new Color(colorStrings[i], colorInts[i], iconSize, strokeWidth);
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
private static class Color {
|
||||
|
||||
private String mLabel;
|
||||
private int mColor;
|
||||
private ShapeDrawable mDrawable;
|
||||
|
||||
private Color(String label, int color, int iconSize, int strokeWidth) {
|
||||
mLabel = label;
|
||||
mColor = color;
|
||||
mDrawable = new ShapeDrawable(new OvalShape());
|
||||
mDrawable.setIntrinsicHeight(iconSize);
|
||||
mDrawable.setIntrinsicWidth(iconSize);
|
||||
mDrawable.getPaint().setStrokeWidth(strokeWidth);
|
||||
mDrawable.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
|
||||
mDrawable.getPaint().setColor(color);
|
||||
}
|
||||
|
||||
private String getLabel() {
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
private int getColor() {
|
||||
return mColor;
|
||||
}
|
||||
|
||||
private ShapeDrawable getDrawable() {
|
||||
return mDrawable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ import android.media.AudioManager;
|
||||
import android.media.AudioSystem;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.Utils;
|
||||
|
||||
@@ -30,6 +31,7 @@ import com.android.settings.Utils;
|
||||
*/
|
||||
public class AudioHelper {
|
||||
|
||||
private static final String TAG = "AudioHelper";
|
||||
private Context mContext;
|
||||
private AudioManager mAudioManager;
|
||||
|
||||
@@ -76,6 +78,15 @@ public class AudioHelper {
|
||||
}
|
||||
|
||||
public int getMinVolume(int stream) {
|
||||
return mAudioManager.getStreamMinVolume(stream);
|
||||
int minVolume;
|
||||
try {
|
||||
minVolume = mAudioManager.getStreamMinVolume(stream);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.w(TAG, "Invalid stream type " + stream);
|
||||
// Fallback to STREAM_VOICE_CALL because CallVolumePreferenceController.java default
|
||||
// return STREAM_VOICE_CALL in getAudioStream
|
||||
minVolume = mAudioManager.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL);
|
||||
}
|
||||
return minVolume;
|
||||
}
|
||||
}
|
||||
|
@@ -117,11 +117,13 @@ public class ImportancePreference extends Preference {
|
||||
case IMPORTANCE_LOW:
|
||||
mAlertButton.setBackground(unselectedBackground);
|
||||
mSilenceButton.setBackground(selectedBackground);
|
||||
mSilenceButton.setSelected(true);
|
||||
break;
|
||||
case IMPORTANCE_HIGH:
|
||||
default:
|
||||
mSilenceButton.setBackground(unselectedBackground);
|
||||
mAlertButton.setBackground(selectedBackground);
|
||||
mAlertButton.setSelected(true);
|
||||
break;
|
||||
}
|
||||
setImportanceSummary((ViewGroup) holder.itemView, mImportance, false);
|
||||
|
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.Button;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
public class NotificationButtonRelativeLayout extends RelativeLayout {
|
||||
|
||||
public NotificationButtonRelativeLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getAccessibilityClassName() {
|
||||
return Button.class.getName();
|
||||
}
|
||||
}
|
@@ -281,7 +281,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
|
||||
}
|
||||
|
||||
private Drawable getAlertingIcon() {
|
||||
Drawable icon = getContext().getDrawable(R.drawable.ic_notifications);
|
||||
Drawable icon = getContext().getDrawable(R.drawable.ic_notifications_alert);
|
||||
icon.setTintList(Utils.getColorAccent(getContext()));
|
||||
return icon;
|
||||
}
|
||||
|
@@ -96,18 +96,23 @@ public final class EnableContentCaptureWithServiceSettingsPreferenceController
|
||||
for (UserInfo info: userInfos) {
|
||||
userHandles.add(info.getUserHandle());
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
UserAdapter adapter = UserAdapter.createUserAdapter(userManager, context, userHandles);
|
||||
builder.setTitle(com.android.settingslib.R.string.choose_profile)
|
||||
.setAdapter(adapter, (DialogInterface dialog, int which) -> {
|
||||
final UserHandle user = userHandles.get(which);
|
||||
// Show menu on top level items.
|
||||
final Intent intent = pref.getIntent();
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
context.startActivityAsUser(intent, user);
|
||||
})
|
||||
.show();
|
||||
if (userHandles.size() == 1) {
|
||||
final Intent intent = pref.getIntent().addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
context.startActivityAsUser(intent, userHandles.get(0));
|
||||
} else {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
UserAdapter adapter = UserAdapter.createUserAdapter(userManager, context,
|
||||
userHandles);
|
||||
builder.setTitle(com.android.settingslib.R.string.choose_profile)
|
||||
.setAdapter(adapter, (DialogInterface dialog, int which) -> {
|
||||
final UserHandle user = userHandles.get(which);
|
||||
// Show menu on top level items.
|
||||
final Intent intent = pref.getIntent()
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
context.startActivityAsUser(intent, user);
|
||||
})
|
||||
.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.security;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.provider.Settings;
|
||||
|
||||
@@ -30,7 +31,9 @@ public class LockscreenBypassPreferenceController extends TogglePreferenceContro
|
||||
|
||||
public LockscreenBypassPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mFaceManager = context.getSystemService(FaceManager.class);
|
||||
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
|
||||
mFaceManager = context.getSystemService(FaceManager.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -26,6 +26,7 @@ import android.util.ArrayMap;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.display.AdaptiveSleepPreferenceController;
|
||||
import com.android.settings.flashlight.FlashlightSlice;
|
||||
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
|
||||
import com.android.settings.homepage.contextualcards.deviceinfo.DataUsageSlice;
|
||||
@@ -34,6 +35,7 @@ import com.android.settings.homepage.contextualcards.deviceinfo.EmergencyInfoSli
|
||||
import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
|
||||
import com.android.settings.homepage.contextualcards.slices.NotificationChannelSlice;
|
||||
@@ -64,6 +66,16 @@ public class CustomSliceRegistry {
|
||||
.appendPath(SettingsSlicesContract.KEY_AIRPLANE_MODE)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Uri for Contextual Adaptive Sleep Slice
|
||||
*/
|
||||
public static final Uri CONTEXTUAL_ADAPTIVE_SLEEP_URI = new Uri.Builder()
|
||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
|
||||
.appendPath(SettingsSlicesContract.PATH_SETTING_INTENT)
|
||||
.appendPath(AdaptiveSleepPreferenceController.PREF_NAME)
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Uri for Battery Fix Slice.
|
||||
*/
|
||||
@@ -328,6 +340,7 @@ public class CustomSliceRegistry {
|
||||
|
||||
sUriToSlice.put(BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
|
||||
sUriToSlice.put(BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
|
||||
sUriToSlice.put(CONTEXTUAL_ADAPTIVE_SLEEP_URI, ContextualAdaptiveSleepSlice.class);
|
||||
sUriToSlice.put(CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI,
|
||||
ContextualNotificationChannelSlice.class);
|
||||
sUriToSlice.put(CONTEXTUAL_WIFI_SLICE_URI, ContextualWifiSlice.class);
|
||||
@@ -337,12 +350,12 @@ public class CustomSliceRegistry {
|
||||
sUriToSlice.put(FLASHLIGHT_SLICE_URI, FlashlightSlice.class);
|
||||
sUriToSlice.put(LOCATION_SLICE_URI, LocationSlice.class);
|
||||
sUriToSlice.put(LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
|
||||
sUriToSlice.put(MEDIA_OUTPUT_INDICATOR_SLICE_URI, MediaOutputIndicatorSlice.class);
|
||||
sUriToSlice.put(MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
|
||||
sUriToSlice.put(MOBILE_DATA_SLICE_URI, MobileDataSlice.class);
|
||||
sUriToSlice.put(NOTIFICATION_CHANNEL_SLICE_URI, NotificationChannelSlice.class);
|
||||
sUriToSlice.put(STORAGE_SLICE_URI, StorageSlice.class);
|
||||
sUriToSlice.put(WIFI_SLICE_URI, WifiSlice.class);
|
||||
sUriToSlice.put(MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
|
||||
sUriToSlice.put(MEDIA_OUTPUT_INDICATOR_SLICE_URI, MediaOutputIndicatorSlice.class);
|
||||
}
|
||||
|
||||
public static Class<? extends CustomSliceable> getSliceClassByUri(Uri uri) {
|
||||
|
@@ -40,7 +40,8 @@ public class SlicePreferenceController extends BasePreferenceController implemen
|
||||
LifecycleObserver, OnStart, OnStop, Observer<Slice> {
|
||||
@VisibleForTesting
|
||||
LiveData<Slice> mLiveData;
|
||||
private SlicePreference mSlicePreference;
|
||||
@VisibleForTesting
|
||||
SlicePreference mSlicePreference;
|
||||
private Uri mUri;
|
||||
|
||||
public SlicePreferenceController(Context context, String preferenceKey) {
|
||||
@@ -82,8 +83,6 @@ public class SlicePreferenceController extends BasePreferenceController implemen
|
||||
|
||||
@Override
|
||||
public void onChanged(Slice slice) {
|
||||
if (slice != null) {
|
||||
mSlicePreference.onSliceUpdated(slice);
|
||||
}
|
||||
mSlicePreference.onSliceUpdated(slice);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
public class RadioButtonPreferenceWithExtraWidget extends RadioButtonPreference {
|
||||
public static final int EXTRA_WIDGET_VISIBILITY_GONE = 0;
|
||||
public static final int EXTRA_WIDGET_VISIBILITY_INFO = 1;
|
||||
|
||||
private View mExtraWidgetDivider;
|
||||
private ImageView mExtraWidget;
|
||||
|
||||
private int mExtraWidgetVisibility = EXTRA_WIDGET_VISIBILITY_GONE;
|
||||
private View.OnClickListener mExtraWidgetOnClickListener;
|
||||
|
||||
public RadioButtonPreferenceWithExtraWidget(Context context) {
|
||||
super(context, null);
|
||||
setLayoutResource(R.layout.preference_radio_with_extra_widget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||
super.onBindViewHolder(view);
|
||||
|
||||
mExtraWidget = (ImageView) view.findViewById(R.id.radio_extra_widget);
|
||||
mExtraWidgetDivider = view.findViewById(R.id.radio_extra_widget_divider);
|
||||
setExtraWidgetVisibility(mExtraWidgetVisibility);
|
||||
|
||||
if (mExtraWidgetOnClickListener != null) {
|
||||
setExtraWidgetOnClickListener(mExtraWidgetOnClickListener);
|
||||
}
|
||||
}
|
||||
|
||||
public void setExtraWidgetVisibility(int visibility) {
|
||||
mExtraWidgetVisibility = visibility;
|
||||
if (mExtraWidget == null || mExtraWidgetDivider == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (visibility == EXTRA_WIDGET_VISIBILITY_GONE) {
|
||||
mExtraWidget.setClickable(false);
|
||||
mExtraWidget.setVisibility(View.GONE);
|
||||
mExtraWidgetDivider.setVisibility(View.GONE);
|
||||
} else {
|
||||
mExtraWidget.setClickable(true);
|
||||
mExtraWidget.setVisibility(View.VISIBLE);
|
||||
mExtraWidgetDivider.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setExtraWidgetOnClickListener(View.OnClickListener listener) {
|
||||
mExtraWidgetOnClickListener = listener;
|
||||
if (mExtraWidget != null) {
|
||||
mExtraWidget.setEnabled(true);
|
||||
mExtraWidget.setOnClickListener(listener);
|
||||
}
|
||||
}
|
||||
}
|
@@ -20,12 +20,14 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ModuleInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.UserManager;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
@@ -94,6 +96,7 @@ public class BatteryAppListPreferenceControllerTest {
|
||||
when(mNormalBatterySipper.getPackages()).thenReturn(PACKAGE_NAMES);
|
||||
when(mNormalBatterySipper.getUid()).thenReturn(UID);
|
||||
mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
|
||||
mNormalBatterySipper.uidObj = mock(BatteryStats.Uid.class);
|
||||
|
||||
mPreferenceController = new BatteryAppListPreferenceController(mContext, KEY_APP_LIST, null,
|
||||
mSettingsActivity, mFragment);
|
||||
@@ -203,15 +206,7 @@ public class BatteryAppListPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void testShouldHideSipper_hiddenSystemModule_returnTrue() {
|
||||
ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", null);
|
||||
final String packageName = "test.hidden.module";
|
||||
final ModuleInfo moduleInfo = new ModuleInfo();
|
||||
moduleInfo.setPackageName(packageName);
|
||||
moduleInfo.setHidden(true);
|
||||
final List<ModuleInfo> modules = new ArrayList<>();
|
||||
modules.add(moduleInfo);
|
||||
when(mBatteryUtils.getPackageName(anyInt() /* uid */)).thenReturn(packageName);
|
||||
when(mPackageManager.getInstalledModules(anyInt() /* flags */)).thenReturn(modules);
|
||||
when(mBatteryUtils.isHiddenSystemModule(mNormalBatterySipper)).thenReturn(true);
|
||||
|
||||
assertThat(mPreferenceController.shouldHideSipper(mNormalBatterySipper)).isTrue();
|
||||
}
|
||||
|
@@ -368,6 +368,15 @@ public class BatteryUtilsTest {
|
||||
assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShouldHideSipper_hiddenSystemModule_ReturnTrue() {
|
||||
mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
|
||||
when(mNormalBatterySipper.getUid()).thenReturn(UID);
|
||||
when(mBatteryUtils.isHiddenSystemModule(mNormalBatterySipper)).thenReturn(true);
|
||||
|
||||
assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateBatteryPercent() {
|
||||
assertThat(mBatteryUtils.calculateBatteryPercent(BATTERY_SYSTEM_USAGE, TOTAL_BATTERY_USAGE,
|
||||
|
@@ -18,6 +18,7 @@ package com.android.settings.fuelgauge.batterytip.detectors;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -40,6 +41,7 @@ import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
|
||||
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;
|
||||
@@ -52,22 +54,25 @@ import java.util.List;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class HighUsageDetectorTest {
|
||||
private static final int UID_HIGH = 123;
|
||||
private static final int UID_ZERO = 345;
|
||||
private static final long SCREEN_ON_TIME_MS = DateUtils.HOUR_IN_MILLIS;
|
||||
private static final int UID_LOW = 345;
|
||||
private static final double POWER_HIGH = 20000;
|
||||
private static final double POWER_LOW = 10000;
|
||||
private Context mContext;
|
||||
@Mock
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private BatteryStatsHelper mBatteryStatsHelper;
|
||||
@Mock
|
||||
private BatteryUtils mBatteryUtils;
|
||||
@Mock
|
||||
private BatterySipper mHighBatterySipper;
|
||||
@Mock
|
||||
private BatterySipper mZeroBatterySipper;
|
||||
private BatterySipper mLowBatterySipper;
|
||||
@Mock
|
||||
private BatterySipper mSystemBatterySipper;
|
||||
@Mock
|
||||
private HighUsageDataParser mDataParser;
|
||||
|
||||
private AppInfo mAppInfo;
|
||||
private AppInfo mHighAppInfo;
|
||||
private AppInfo mLowAppInfo;
|
||||
private BatteryTipPolicy mPolicy;
|
||||
private BatteryUtils mBatteryUtils;
|
||||
private HighUsageDetector mHighUsageDetector;
|
||||
private List<BatterySipper> mUsageList;
|
||||
|
||||
@@ -77,28 +82,37 @@ public class HighUsageDetectorTest {
|
||||
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mPolicy = spy(new BatteryTipPolicy(mContext));
|
||||
mBatteryUtils = spy(BatteryUtils.getInstance(mContext));
|
||||
mHighUsageDetector = spy(new HighUsageDetector(mContext, mPolicy, mBatteryStatsHelper,
|
||||
true /* mDischarging */));
|
||||
mHighUsageDetector.mBatteryUtils = mBatteryUtils;
|
||||
mHighUsageDetector.mDataParser = mDataParser;
|
||||
doNothing().when(mHighUsageDetector).parseBatteryData();
|
||||
doReturn(UID_HIGH).when(mHighBatterySipper).getUid();
|
||||
doReturn(UID_LOW).when(mLowBatterySipper).getUid();
|
||||
mHighBatterySipper.uidObj = mock(BatteryStats.Uid.class);
|
||||
mZeroBatterySipper.uidObj = mock(BatteryStats.Uid.class);
|
||||
doReturn(UID_ZERO).when(mZeroBatterySipper).getUid();
|
||||
mAppInfo = new AppInfo.Builder()
|
||||
mHighBatterySipper.drainType = BatterySipper.DrainType.APP;
|
||||
mHighBatterySipper.totalSmearedPowerMah = POWER_HIGH;
|
||||
mLowBatterySipper.uidObj = mock(BatteryStats.Uid.class);
|
||||
mLowBatterySipper.drainType = BatterySipper.DrainType.APP;
|
||||
mLowBatterySipper.totalSmearedPowerMah = POWER_LOW;
|
||||
when(mBatteryUtils.shouldHideSipper(mSystemBatterySipper)).thenReturn(true);
|
||||
when(mBatteryUtils.shouldHideSipper(mHighBatterySipper)).thenReturn(false);
|
||||
when(mBatteryUtils.shouldHideSipper(mLowBatterySipper)).thenReturn(false);
|
||||
when(mBatteryStatsHelper.getStats().getDischargeAmount(anyInt())).thenReturn(100);
|
||||
when(mBatteryStatsHelper.getTotalPower()).thenReturn(POWER_HIGH + POWER_LOW);
|
||||
|
||||
|
||||
mHighAppInfo = new AppInfo.Builder()
|
||||
.setUid(UID_HIGH)
|
||||
.setScreenOnTimeMs(SCREEN_ON_TIME_MS)
|
||||
.build();
|
||||
mLowAppInfo = new AppInfo.Builder()
|
||||
.setUid(UID_LOW)
|
||||
.build();
|
||||
|
||||
doReturn(SCREEN_ON_TIME_MS).when(mBatteryUtils).getProcessTimeMs(
|
||||
BatteryUtils.StatusType.FOREGROUND, mHighBatterySipper.uidObj,
|
||||
BatteryStats.STATS_SINCE_CHARGED);
|
||||
doReturn(0L).when(mBatteryUtils).getProcessTimeMs(
|
||||
BatteryUtils.StatusType.FOREGROUND, mZeroBatterySipper.uidObj,
|
||||
BatteryStats.STATS_SINCE_CHARGED);
|
||||
|
||||
mUsageList = new ArrayList<>();
|
||||
mUsageList.add(mSystemBatterySipper);
|
||||
mUsageList.add(mLowBatterySipper);
|
||||
mUsageList.add(mHighBatterySipper);
|
||||
when(mBatteryStatsHelper.getUsageList()).thenReturn(mUsageList);
|
||||
}
|
||||
@@ -128,21 +142,15 @@ public class HighUsageDetectorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetect_containsHighUsageApp_tipVisible() {
|
||||
public void testDetect_containsHighUsageApp_tipVisibleAndSorted() {
|
||||
doReturn(true).when(mDataParser).isDeviceHeavilyUsed();
|
||||
|
||||
final HighUsageTip highUsageTip = (HighUsageTip) mHighUsageDetector.detect();
|
||||
assertThat(highUsageTip.isVisible()).isTrue();
|
||||
assertThat(highUsageTip.getHighUsageAppList()).containsExactly(mAppInfo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetect_containsHighUsageApp_removeZeroOne() {
|
||||
doReturn(true).when(mDataParser).isDeviceHeavilyUsed();
|
||||
mUsageList.add(mZeroBatterySipper);
|
||||
|
||||
final HighUsageTip highUsageTip = (HighUsageTip) mHighUsageDetector.detect();
|
||||
assertThat(highUsageTip.isVisible()).isTrue();
|
||||
assertThat(highUsageTip.getHighUsageAppList()).containsExactly(mAppInfo);
|
||||
// Contain two appInfo and large one comes first
|
||||
final List<AppInfo> appInfos = highUsageTip.getHighUsageAppList();
|
||||
assertThat(appInfos).containsExactly(mLowAppInfo, mHighAppInfo);
|
||||
assertThat(appInfos.get(0)).isEqualTo(mHighAppInfo);
|
||||
}
|
||||
}
|
||||
|
@@ -24,10 +24,14 @@ import static com.android.settings.gestures.SystemNavigationPreferenceController
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.text.TextUtils;
|
||||
@@ -39,6 +43,7 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
@@ -53,9 +58,15 @@ public class SystemNavigationPreferenceControllerTest {
|
||||
private Context mContext;
|
||||
private ShadowPackageManager mPackageManager;
|
||||
|
||||
@Mock
|
||||
private Context mMockContext;
|
||||
@Mock
|
||||
private PackageManager mMockPackageManager;
|
||||
|
||||
private SystemNavigationPreferenceController mController;
|
||||
|
||||
private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
|
||||
private static final String TEST_RECENTS_COMPONENT_NAME = "test.component.name/.testActivity";
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -69,6 +80,10 @@ public class SystemNavigationPreferenceControllerTest {
|
||||
|
||||
mController = new SystemNavigationPreferenceController(mContext,
|
||||
PREF_KEY_SYSTEM_NAVIGATION);
|
||||
|
||||
when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
|
||||
when(mMockContext.getString(com.android.internal.R.string.config_recentsComponentName))
|
||||
.thenReturn(TEST_RECENTS_COMPONENT_NAME);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -166,4 +181,46 @@ public class SystemNavigationPreferenceControllerTest {
|
||||
assertThat(TextUtils.equals(mController.getSummary(), mContext.getText(
|
||||
com.android.settings.R.string.swipe_up_to_switch_apps_title))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsGestureNavSupportedByDefaultLauncher_noDefaultLauncher() {
|
||||
when(mMockPackageManager.getHomeActivities(any())).thenReturn(null);
|
||||
assertThat(SystemNavigationPreferenceController
|
||||
.isGestureNavSupportedByDefaultLauncher(mMockContext)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsGestureNavSupportedByDefaultLauncher_supported() {
|
||||
when(mMockPackageManager.getHomeActivities(any())).thenReturn(
|
||||
ComponentName.unflattenFromString(TEST_RECENTS_COMPONENT_NAME));
|
||||
assertThat(SystemNavigationPreferenceController
|
||||
.isGestureNavSupportedByDefaultLauncher(mMockContext)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsGestureNavSupportedByDefaultLauncher_notSupported() {
|
||||
when(mMockPackageManager.getHomeActivities(any())).thenReturn(
|
||||
new ComponentName("unsupported", "launcher"));
|
||||
assertThat(SystemNavigationPreferenceController
|
||||
.isGestureNavSupportedByDefaultLauncher(mMockContext)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDefaultHomeAppName_noDefaultLauncher() {
|
||||
when(mMockPackageManager.getHomeActivities(any())).thenReturn(null);
|
||||
assertThat(SystemNavigationPreferenceController
|
||||
.getDefaultHomeAppName(mMockContext)).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDefaultHomeAppName_defaultLauncherExists() throws Exception {
|
||||
when(mMockPackageManager.getHomeActivities(any())).thenReturn(
|
||||
new ComponentName("supported", "launcher"));
|
||||
ApplicationInfo info = new ApplicationInfo();
|
||||
when(mMockPackageManager.getApplicationInfo("supported", 0)).thenReturn(info);
|
||||
when(mMockPackageManager.getApplicationLabel(info)).thenReturn("Test Home App");
|
||||
|
||||
assertThat(SystemNavigationPreferenceController
|
||||
.getDefaultHomeAppName(mMockContext)).isEqualTo("Test Home App");
|
||||
}
|
||||
}
|
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.homepage.contextualcards.slices;
|
||||
|
||||
import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.DEFERRED_TIME_DAYS;
|
||||
import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF;
|
||||
import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF_KEY_SETUP_TIME;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.SliceProvider;
|
||||
import androidx.slice.widget.SliceLiveData;
|
||||
|
||||
import com.android.settings.slices.CustomSliceRegistry;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ContextualAdaptiveSleepSliceTest {
|
||||
|
||||
private static final String pkgName = "adaptive_sleep";
|
||||
private Context mContext;
|
||||
private ContextualAdaptiveSleepSlice mContextualAdaptiveSleepSlice;
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
private SharedPreferences mSharedPreferences;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mContextualAdaptiveSleepSlice = spy(new ContextualAdaptiveSleepSlice(mContext));
|
||||
|
||||
doReturn(mPackageManager).when(mContext).getPackageManager();
|
||||
doReturn(mSharedPreferences).when(mContext).getSharedPreferences(eq(PREF), anyInt());
|
||||
doReturn(true).when(mContextualAdaptiveSleepSlice).isSettingsAvailable();
|
||||
doReturn(pkgName).when(mPackageManager).getAttentionServicePackageName();
|
||||
doReturn(-DEFERRED_TIME_DAYS).when(mSharedPreferences).getLong(eq(PREF_KEY_SETUP_TIME),
|
||||
anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUri_shouldReturnContextualAdaptiveSleepSliceUri() {
|
||||
final Uri uri = mContextualAdaptiveSleepSlice.getUri();
|
||||
|
||||
assertThat(uri).isEqualTo(CustomSliceRegistry.CONTEXTUAL_ADAPTIVE_SLEEP_URI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSlice_ShowIfFeatureIsAvailable() {
|
||||
final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
|
||||
|
||||
assertThat(slice).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSlice_DoNotShowIfFeatureIsUnavailable() {
|
||||
doReturn(false).when(mContextualAdaptiveSleepSlice).isSettingsAvailable();
|
||||
|
||||
final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
|
||||
|
||||
assertThat(slice).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSlice_ShowIfNotRecentlySetup() {
|
||||
final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
|
||||
|
||||
assertThat(slice).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSlice_DoNotShowIfRecentlySetup() {
|
||||
doReturn(System.currentTimeMillis()).when(mSharedPreferences).getLong(
|
||||
eq(PREF_KEY_SETUP_TIME), anyLong());
|
||||
|
||||
final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
|
||||
|
||||
assertThat(slice).isNull();
|
||||
}
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.network;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class MobileNetworkListFragmentTest {
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
|
||||
private MobileNetworkListFragment mFragment;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mFragment = new MobileNetworkListFragment();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isPageSearchEnabled_adminUser_shouldReturnTrue() {
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
when(mUserManager.isAdminUser()).thenReturn(true);
|
||||
final BaseSearchIndexProvider provider =
|
||||
(BaseSearchIndexProvider) mFragment.SEARCH_INDEX_DATA_PROVIDER;
|
||||
|
||||
final Object obj = ReflectionHelpers.callInstanceMethod(provider, "isPageSearchEnabled",
|
||||
ReflectionHelpers.ClassParameter.from(Context.class, mContext));
|
||||
final boolean isEnabled = (Boolean) obj;
|
||||
|
||||
assertThat(isEnabled).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isPageSearchEnabled_nonAdminUser_shouldReturnFalse() {
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
when(mUserManager.isAdminUser()).thenReturn(false);
|
||||
final BaseSearchIndexProvider provider =
|
||||
(BaseSearchIndexProvider) mFragment.SEARCH_INDEX_DATA_PROVIDER;
|
||||
|
||||
final Object obj = ReflectionHelpers.callInstanceMethod(provider, "isPageSearchEnabled",
|
||||
ReflectionHelpers.ClassParameter.from(Context.class, mContext));
|
||||
final boolean isEnabled = (Boolean) obj;
|
||||
|
||||
assertThat(isEnabled).isFalse();
|
||||
}
|
||||
}
|
@@ -30,6 +30,7 @@ import android.app.usage.NetworkStatsManager;
|
||||
import android.content.Context;
|
||||
import android.net.NetworkPolicyManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
@@ -38,6 +39,7 @@ import androidx.fragment.app.FragmentActivity;
|
||||
import com.android.settings.core.FeatureFlags;
|
||||
import com.android.settings.datausage.DataUsageSummaryPreferenceController;
|
||||
import com.android.settings.development.featureflags.FeatureFlagPersistent;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
@@ -50,6 +52,7 @@ import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -135,4 +138,34 @@ public class MobileNetworkSettingsTest {
|
||||
mFragment.onActivityResult(REQUEST_CODE_DELETE_SUBSCRIPTION, 0, null);
|
||||
verify(mActivity).finish();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isPageSearchEnabled_adminUser_shouldReturnTrue() {
|
||||
final UserManager userManager = mock(UserManager.class);
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(userManager);
|
||||
when(userManager.isAdminUser()).thenReturn(true);
|
||||
final BaseSearchIndexProvider provider =
|
||||
(BaseSearchIndexProvider) mFragment.SEARCH_INDEX_DATA_PROVIDER;
|
||||
|
||||
final Object obj = ReflectionHelpers.callInstanceMethod(provider, "isPageSearchEnabled",
|
||||
ReflectionHelpers.ClassParameter.from(Context.class, mContext));
|
||||
final boolean isEnabled = (Boolean) obj;
|
||||
|
||||
assertThat(isEnabled).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isPageSearchEnabled_nonAdminUser_shouldReturnFalse() {
|
||||
final UserManager userManager = mock(UserManager.class);
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(userManager);
|
||||
when(userManager.isAdminUser()).thenReturn(false);
|
||||
final BaseSearchIndexProvider provider =
|
||||
(BaseSearchIndexProvider) mFragment.SEARCH_INDEX_DATA_PROVIDER;
|
||||
|
||||
final Object obj = ReflectionHelpers.callInstanceMethod(provider, "isPageSearchEnabled",
|
||||
ReflectionHelpers.ClassParameter.from(Context.class, mContext));
|
||||
final boolean isEnabled = (Boolean) obj;
|
||||
|
||||
assertThat(isEnabled).isFalse();
|
||||
}
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.Color;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
@@ -38,6 +39,7 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
@@ -58,6 +60,7 @@ import org.robolectric.annotation.Config;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = ShadowAlertDialogCompat.class)
|
||||
public class RenameMobileNetworkDialogFragmentTest {
|
||||
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyMgr;
|
||||
@Mock
|
||||
@@ -95,7 +98,7 @@ public class RenameMobileNetworkDialogFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dialog_cancelButtonClicked_setDisplayNameNotCalled() {
|
||||
public void dialog_cancelButtonClicked_setDisplayNameAndIconTintNotCalled() {
|
||||
when(mSubscriptionMgr.getActiveSubscriptionInfo(mSubscriptionId)).thenReturn(
|
||||
mSubscriptionInfo);
|
||||
final AlertDialog dialog = startDialog();
|
||||
@@ -106,10 +109,11 @@ public class RenameMobileNetworkDialogFragmentTest {
|
||||
negativeButton.performClick();
|
||||
|
||||
verify(mSubscriptionMgr, never()).setDisplayName(anyString(), anyInt(), anyInt());
|
||||
verify(mSubscriptionMgr, never()).setIconTint(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dialog_renameButtonClicked_setDisplayNameCalled() {
|
||||
public void dialog_saveButtonClicked_setDisplayNameAndIconTint() {
|
||||
when(mSubscriptionMgr.getActiveSubscriptionInfo(mSubscriptionId)).thenReturn(
|
||||
mSubscriptionInfo);
|
||||
|
||||
@@ -117,6 +121,9 @@ public class RenameMobileNetworkDialogFragmentTest {
|
||||
final EditText nameView = mFragment.getNameView();
|
||||
nameView.setText("test2");
|
||||
|
||||
final Spinner colorSpinnerView = mFragment.getColorSpinnerView();
|
||||
colorSpinnerView.setSelection(0);
|
||||
|
||||
final Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
positiveButton.performClick();
|
||||
|
||||
@@ -124,6 +131,8 @@ public class RenameMobileNetworkDialogFragmentTest {
|
||||
verify(mSubscriptionMgr).setDisplayName(captor.capture(), eq(mSubscriptionId),
|
||||
eq(SubscriptionManager.NAME_SOURCE_USER_INPUT));
|
||||
assertThat(captor.getValue()).isEqualTo("test2");
|
||||
verify(mSubscriptionMgr)
|
||||
.setIconTint(eq(Color.parseColor("#ff00796b" /* teal */)), eq(mSubscriptionId));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -140,7 +149,9 @@ public class RenameMobileNetworkDialogFragmentTest {
|
||||
assertThat(view.findViewById(R.id.number_label).getVisibility()).isEqualTo(View.GONE);
|
||||
}
|
||||
|
||||
/** Helper method to start the dialog */
|
||||
/**
|
||||
* Helper method to start the dialog
|
||||
*/
|
||||
private AlertDialog startDialog() {
|
||||
mFragment.show(mActivity.getSupportFragmentManager(), null);
|
||||
return ShadowAlertDialogCompat.getLatestAlertDialog();
|
||||
|
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class AudioHelperTest {
|
||||
|
||||
private static final int START = -10;
|
||||
private static final int END = 10;
|
||||
private static final int DEFAULT = -100;
|
||||
|
||||
private Context mContext;
|
||||
private AudioHelper mAudioHelper;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mAudioHelper = new AudioHelper(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMaxVolume_anyStreamType_getValue() {
|
||||
int volume = DEFAULT;
|
||||
|
||||
for (int i = START; i < END; i++) {
|
||||
volume = mAudioHelper.getMaxVolume(i);
|
||||
assertThat(volume).isNotEqualTo(DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMinVolume_anyStreamType_getValue() {
|
||||
int volume = DEFAULT;
|
||||
|
||||
for (int i = START; i < END; i++) {
|
||||
volume = mAudioHelper.getMinVolume(i);
|
||||
assertThat(volume).isNotEqualTo(DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
@@ -41,6 +41,8 @@ public class SlicePreferenceControllerTest {
|
||||
|
||||
@Mock
|
||||
private LiveData<Slice> mLiveData;
|
||||
@Mock
|
||||
private SlicePreference mSlicePreference;
|
||||
private Context mContext;
|
||||
private SlicePreferenceController mController;
|
||||
private Uri mUri;
|
||||
@@ -53,6 +55,7 @@ public class SlicePreferenceControllerTest {
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mController = new SlicePreferenceController(mContext, KEY);
|
||||
mController.mLiveData = mLiveData;
|
||||
mController.mSlicePreference = mSlicePreference;
|
||||
mUri = Uri.EMPTY;
|
||||
}
|
||||
|
||||
@@ -78,4 +81,11 @@ public class SlicePreferenceControllerTest {
|
||||
mController.onStop();
|
||||
verify(mLiveData).removeObserver(mController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onChanged_nullSlice_updateSlice() {
|
||||
mController.onChanged(null);
|
||||
|
||||
verify(mController.mSlicePreference).onSliceUpdated(null);
|
||||
}
|
||||
}
|
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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.widget;
|
||||
|
||||
import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_GONE;
|
||||
import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_INFO;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.app.Application;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class RadioButtonPreferenceWithExtraWidgetTest {
|
||||
|
||||
private Application mContext;
|
||||
private RadioButtonPreferenceWithExtraWidget mPreference;
|
||||
|
||||
private TextView mSummary;
|
||||
private ImageView mExtraWidget;
|
||||
private View mExtraWidgetDivider;
|
||||
|
||||
private boolean mIsClickListenerCalled = false;
|
||||
private View.OnClickListener mClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mIsClickListenerCalled = true;
|
||||
}
|
||||
};
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mPreference = new RadioButtonPreferenceWithExtraWidget(mContext);
|
||||
mPreference.setSummary("test summary");
|
||||
|
||||
View view = LayoutInflater.from(mContext)
|
||||
.inflate(R.layout.preference_radio_with_extra_widget, null);
|
||||
PreferenceViewHolder preferenceViewHolder =
|
||||
PreferenceViewHolder.createInstanceForTests(view);
|
||||
mPreference.onBindViewHolder(preferenceViewHolder);
|
||||
|
||||
mSummary = view.findViewById(android.R.id.summary);
|
||||
mExtraWidget = view.findViewById(R.id.radio_extra_widget);
|
||||
mExtraWidgetDivider = view.findViewById(R.id.radio_extra_widget_divider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHaveRadioPreferenceWithExtraWidgetLayout() {
|
||||
assertThat(mPreference.getLayoutResource())
|
||||
.isEqualTo(R.layout.preference_radio_with_extra_widget);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void iconSpaceReservedShouldBeFalse() {
|
||||
assertThat(mPreference.isIconSpaceReserved()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void summaryShouldBeVisible() {
|
||||
assertEquals(View.VISIBLE, mSummary.getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetExtraWidgetVisibility_gone() {
|
||||
mPreference.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_GONE);
|
||||
assertEquals(View.GONE, mExtraWidget.getVisibility());
|
||||
assertEquals(View.GONE, mExtraWidgetDivider.getVisibility());
|
||||
assertThat(mExtraWidget.isClickable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetExtraWidgetVisibility_info() {
|
||||
mPreference.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_INFO);
|
||||
assertEquals(View.VISIBLE, mExtraWidget.getVisibility());
|
||||
assertEquals(View.VISIBLE, mExtraWidgetDivider.getVisibility());
|
||||
assertThat(mExtraWidget.isClickable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetExtraWidgetOnClickListener() {
|
||||
mPreference.setExtraWidgetOnClickListener(mClickListener);
|
||||
|
||||
assertThat(mIsClickListenerCalled).isFalse();
|
||||
mExtraWidget.callOnClick();
|
||||
assertThat(mIsClickListenerCalled).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extraWidgetStaysEnabledWhenPreferenceIsDisabled() {
|
||||
mPreference.setEnabled(false);
|
||||
mExtraWidget.setEnabled(false);
|
||||
|
||||
assertThat(mExtraWidget.isEnabled()).isFalse();
|
||||
mPreference.setExtraWidgetOnClickListener(mClickListener);
|
||||
assertThat(mExtraWidget.isEnabled()).isTrue();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user