Snap for 4598635 from 08addde8b5 to pi-release
Change-Id: I0dd217b846bf0a4ebb0b3e345fbec2f2be8ecc4a
This commit is contained in:
File diff suppressed because it is too large
Load Diff
112
res/layout/data_usage_summary_preference.xml
Normal file
112
res/layout/data_usage_summary_preference.xml
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2018 The Android Open Source Project
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at"+
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="@dimen/preference_no_icon_padding_start"
|
||||||
|
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="@drawable/selectable_card_grey"
|
||||||
|
android:selectable="false"
|
||||||
|
style="@style/EntityHeader">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/usage_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:paddingBottom="5dp"
|
||||||
|
android:text="@string/data_usage_title" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="5dp"
|
||||||
|
android:fontFamily="@*android:string/config_headlineFontFamily"
|
||||||
|
android:textColor="?android:attr/colorAccent"
|
||||||
|
android:textAppearance="@android:style/TextAppearance.Material.Large" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/summary"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:paddingBottom="5dp" />
|
||||||
|
|
||||||
|
<com.android.settings.widget.LinearColorBar
|
||||||
|
android:id="@+id/color_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="28dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/label_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="2dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView android:id="@android:id/text1"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||||
|
android:textColor="?android:attr/textColorSecondary" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<TextView android:id="@android:id/text2"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||||
|
android:textColor="?android:attr/textColorSecondary" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/cycle_left_time"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="5dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/carrier_and_update"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="5dp" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/launch_mdp_app_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:text="@string/launch_mdp_app_text"
|
||||||
|
style="@style/ActionPrimaryButton" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/data_limits"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="5dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -25,23 +25,21 @@
|
|||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/battery_saver_on_button"
|
android:id="@+id/state_on_button"
|
||||||
style="@style/ActionPrimaryButton"
|
style="@style/ActionPrimaryButton"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:text="@string/battery_saver_button_turn_on"
|
|
||||||
android:paddingEnd="8dp" />
|
android:paddingEnd="8dp" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/battery_saver_off_button"
|
android:id="@+id/state_off_button"
|
||||||
style="@style/ActionSecondaryButton"
|
style="@style/ActionSecondaryButton"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:text="@string/battery_saver_button_turn_off"
|
|
||||||
android:paddingEnd="8dp" />
|
android:paddingEnd="8dp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -162,4 +162,12 @@
|
|||||||
<attr name="showPercentString" format="boolean" />
|
<attr name="showPercentString" format="boolean" />
|
||||||
<attr name="thickness" format="dimension" />
|
<attr name="thickness" format="dimension" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
|
<!-- For TwoStatesButtonPreference -->
|
||||||
|
<declare-styleable name="TwoStateButtonPreference">
|
||||||
|
<attr name="textOn" format="reference" />
|
||||||
|
<attr name="textOff" format="reference" />
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
|
<attr name="twoStateButtonPreferenceStyle" format="reference" />
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -5844,6 +5844,8 @@
|
|||||||
<string name="data_usage_enable_3g">2G-3G data</string>
|
<string name="data_usage_enable_3g">2G-3G data</string>
|
||||||
<!-- Toggle switch title for enabling 4G data network connection. [CHAR LIMIT=32] -->
|
<!-- Toggle switch title for enabling 4G data network connection. [CHAR LIMIT=32] -->
|
||||||
<string name="data_usage_enable_4g">4G data</string>
|
<string name="data_usage_enable_4g">4G data</string>
|
||||||
|
<!-- Toggle switch title for enabling roaming on the primary data SIM card. [CHAR LIMIT=32] -->
|
||||||
|
<string name="data_roaming_enable_mobile">Roaming</string>
|
||||||
|
|
||||||
<!-- Data Usage Foreground label. [CHAR LIMIT=40] -->
|
<!-- Data Usage Foreground label. [CHAR LIMIT=40] -->
|
||||||
<string name="data_usage_forground_label">Foreground:</string>
|
<string name="data_usage_forground_label">Foreground:</string>
|
||||||
@@ -6476,6 +6478,7 @@
|
|||||||
<string name="help_uri_process_stats_apps" translatable="false"></string>
|
<string name="help_uri_process_stats_apps" translatable="false"></string>
|
||||||
<string name="help_uri_private_dns" translatable="false"></string>
|
<string name="help_uri_private_dns" translatable="false"></string>
|
||||||
<string name="help_uri_about_phone_v2" translatable="false"></string>
|
<string name="help_uri_about_phone_v2" translatable="false"></string>
|
||||||
|
<string name="help_uri_wifi_calling" translatable="false"></string>
|
||||||
|
|
||||||
<!-- User account title [CHAR LIMIT=30] -->
|
<!-- User account title [CHAR LIMIT=30] -->
|
||||||
<string name="user_account_title">Account for content</string>
|
<string name="user_account_title">Account for content</string>
|
||||||
@@ -8655,6 +8658,27 @@
|
|||||||
<item quantity="other"><xliff:g id="count" example="10">%1$d</xliff:g> apps allowed to use unrestricted data when Data Saver is on</item>
|
<item quantity="other"><xliff:g id="count" example="10">%1$d</xliff:g> apps allowed to use unrestricted data when Data Saver is on</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
|
||||||
|
<!-- Data usage title text [CHAR LIMIT=30] -->
|
||||||
|
<string name="data_usage_title">Primary data</string>
|
||||||
|
|
||||||
|
<!-- Data usage string [CHAR LIMIT=30] -->
|
||||||
|
<string name="data_used"><xliff:g name="bytes" example="2 GB">^1</xliff:g> used</string>
|
||||||
|
|
||||||
|
<!-- Optional part of data usage showing the remaining amount [CHAR LIMIT=30] -->
|
||||||
|
<string name="data_remaining"><xliff:g name="bytes" example="2 GB">, ^1</xliff:g> left</string>
|
||||||
|
|
||||||
|
<!-- Informational text about time left in billing cycle [CHAR LIMIT=30] -->
|
||||||
|
<string name="cycle_left_time_text"><xliff:g name="time" example="2d">%1$s</xliff:g> left in this cycle</string>
|
||||||
|
|
||||||
|
<!-- Informational text about carrier and update time [CHAR LIMIT=30] -->
|
||||||
|
<string name="carrier_and_update_text">Updated by <xliff:g name="carrier" example="T-mobile">%1$s</xliff:g> <xliff:g name="time" example="3m">%2$s</xliff:g></string>
|
||||||
|
|
||||||
|
<!-- Informational text about update time only, without carrier [CHAR LIMIT=30] -->
|
||||||
|
<string name="no_carrier_update_text">Updated <xliff:g name="time" example="3m">%1$s</xliff:g></string>
|
||||||
|
|
||||||
|
<!-- Button to launch external data plan app [CHAR LIMIT=30] -->
|
||||||
|
<string name="launch_mdp_app_text">VIEW PLAN</string>
|
||||||
|
|
||||||
<!-- Name of Data Saver screens [CHAR LIMIT=30] -->
|
<!-- Name of Data Saver screens [CHAR LIMIT=30] -->
|
||||||
<string name="data_saver_title">Data saver</string>
|
<string name="data_saver_title">Data saver</string>
|
||||||
|
|
||||||
|
|||||||
@@ -36,4 +36,8 @@
|
|||||||
<item name="android:widgetLayout">@layout/preference_widget_sync_toggle</item>
|
<item name="android:widgetLayout">@layout/preference_widget_sync_toggle</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="TwoStateButtonPreference" parent="Preference.SettingsBase">
|
||||||
|
<item name="android:layout">@layout/two_state_button</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -176,6 +176,7 @@
|
|||||||
<item name="preferenceFragmentStyle">@style/SettingsPreferenceFragmentStyle</item>
|
<item name="preferenceFragmentStyle">@style/SettingsPreferenceFragmentStyle</item>
|
||||||
<item name="apnPreferenceStyle">@style/ApnPreference</item>
|
<item name="apnPreferenceStyle">@style/ApnPreference</item>
|
||||||
<item name="seekBarPreferenceStyle">@style/SettingsSeekBarPreference</item>
|
<item name="seekBarPreferenceStyle">@style/SettingsSeekBarPreference</item>
|
||||||
|
<item name="twoStateButtonPreferenceStyle">@style/TwoStateButtonPreference</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="PreferenceTheme.SetupWizard" parent="PreferenceTheme">
|
<style name="PreferenceTheme.SetupWizard" parent="PreferenceTheme">
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||||
android:title="@string/battery_saver"
|
android:title="@string/battery_saver"
|
||||||
android:key="battery_saver">
|
android:key="battery_saver">
|
||||||
|
|
||||||
@@ -23,16 +24,20 @@
|
|||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="auto_battery_saver"
|
android:key="auto_battery_saver"
|
||||||
android:title="@string/battery_saver_auto_title"
|
android:title="@string/battery_saver_auto_title"
|
||||||
android:summary="@string/battery_saver_auto_summary"/>
|
android:summary="@string/battery_saver_auto_summary"
|
||||||
|
settings:controller="com.android.settings.fuelgauge.batterysaver.AutoBatterySaverPreferenceController"/>
|
||||||
|
|
||||||
<com.android.settings.widget.SeekBarPreference
|
<com.android.settings.widget.SeekBarPreference
|
||||||
android:key="battery_saver_seek_bar"
|
android:key="battery_saver_seek_bar"
|
||||||
android:title="@string/battery_saver_seekbar_title"
|
android:title="@string/battery_saver_seekbar_title"
|
||||||
android:max="75"
|
android:max="75"
|
||||||
android:min="5"/>
|
android:min="5"/>
|
||||||
<com.android.settings.applications.LayoutPreference
|
|
||||||
|
<com.android.settings.widget.TwoStateButtonPreference
|
||||||
android:key="battery_saver_button_container"
|
android:key="battery_saver_button_container"
|
||||||
android:selectable="false"
|
android:selectable="false"
|
||||||
android:layout="@layout/battery_saver_settings_button"/>
|
settings:textOn="@string/battery_saver_button_turn_on"
|
||||||
|
settings:textOff="@string/battery_saver_button_turn_off"/>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="battery_saver_footer">
|
android:key="battery_saver_footer">
|
||||||
|
|||||||
@@ -25,8 +25,8 @@
|
|||||||
android:title="@string/bluetooth_settings_title"
|
android:title="@string/bluetooth_settings_title"
|
||||||
android:icon="@drawable/ic_settings_bluetooth"
|
android:icon="@drawable/ic_settings_bluetooth"
|
||||||
android:summary="@string/bluetooth_pref_summary"
|
android:summary="@string/bluetooth_pref_summary"
|
||||||
settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"
|
android:order="-7"
|
||||||
android:order="-7"/>
|
settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"/>
|
||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="toggle_nfc"
|
android:key="toggle_nfc"
|
||||||
@@ -54,6 +54,7 @@
|
|||||||
android:title="@string/bluetooth_on_while_driving_pref"
|
android:title="@string/bluetooth_on_while_driving_pref"
|
||||||
android:icon="@drawable/ic_settings_bluetooth"
|
android:icon="@drawable/ic_settings_bluetooth"
|
||||||
android:summary="@string/bluetooth_on_while_driving_summary"
|
android:summary="@string/bluetooth_on_while_driving_summary"
|
||||||
|
settings:controller="com.android.settings.connecteddevice.BluetoothOnWhileDrivingPreferenceController"
|
||||||
android:order="-2"/>
|
android:order="-2"/>
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
|
|||||||
@@ -20,24 +20,8 @@
|
|||||||
android:key="data_usage_screen"
|
android:key="data_usage_screen"
|
||||||
android:title="@string/data_usage_summary_title">
|
android:title="@string/data_usage_summary_title">
|
||||||
|
|
||||||
<PreferenceCategory
|
<com.android.settings.datausage.DataUsageSummaryPreference
|
||||||
android:key="data_usage_category"
|
|
||||||
android:title="@string/usage">
|
|
||||||
|
|
||||||
<com.android.settings.SummaryPreference
|
|
||||||
android:key="status_header"
|
android:key="status_header"
|
||||||
android:selectable="false" />
|
android:selectable="false" />
|
||||||
|
|
||||||
<Preference
|
|
||||||
android:key="limit_summary"
|
|
||||||
android:selectable="false"
|
|
||||||
settings:allowDividerBelow="true" />
|
|
||||||
|
|
||||||
<com.android.settings.datausage.DataSaverPreference
|
|
||||||
android:key="restrict_background"
|
|
||||||
android:title="@string/data_saver_title"
|
|
||||||
android:fragment="com.android.settings.datausage.DataSaverSummary" />
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|||||||
@@ -43,8 +43,9 @@
|
|||||||
<com.android.settingslib.RestrictedSwitchPreference
|
<com.android.settingslib.RestrictedSwitchPreference
|
||||||
android:key="auto_brightness"
|
android:key="auto_brightness"
|
||||||
android:title="@string/auto_brightness_title"
|
android:title="@string/auto_brightness_title"
|
||||||
settings:keywords="@string/keywords_display_auto_brightness"
|
|
||||||
android:summary="@string/auto_brightness_summary"
|
android:summary="@string/auto_brightness_summary"
|
||||||
|
settings:keywords="@string/keywords_display_auto_brightness"
|
||||||
|
settings:controller="com.android.settings.display.AutoBrightnessPreferenceController"
|
||||||
settings:useAdminDisabledSummary="true"
|
settings:useAdminDisabledSummary="true"
|
||||||
settings:userRestriction="no_config_brightness" />
|
settings:userRestriction="no_config_brightness" />
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,8 @@
|
|||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="visiblepattern_profile"
|
android:key="visiblepattern_profile"
|
||||||
android:summary="@string/summary_placeholder"
|
android:summary="@string/summary_placeholder"
|
||||||
android:title="@string/lockpattern_settings_enable_visible_pattern_title_profile" />
|
android:title="@string/lockpattern_settings_enable_visible_pattern_title_profile"
|
||||||
|
settings:controller="com.android.settings.security.VisiblePatternProfilePreferenceController"/>
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="fingerprint_settings_profile"
|
android:key="fingerprint_settings_profile"
|
||||||
@@ -103,7 +104,8 @@
|
|||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="show_password"
|
android:key="show_password"
|
||||||
android:title="@string/show_password"
|
android:title="@string/show_password"
|
||||||
android:summary="@string/show_password_summary" />
|
android:summary="@string/show_password_summary"
|
||||||
|
settings:controller="com.android.settings.security.ShowPasswordPreferenceController"/>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||||
android:key="security_lockscreen_settings_screen"
|
android:key="security_lockscreen_settings_screen"
|
||||||
android:title="@string/lockscreen_settings_title">
|
android:title="@string/lockscreen_settings_title">
|
||||||
|
|
||||||
@@ -36,7 +37,8 @@
|
|||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="security_setting_lockdown_enabled"
|
android:key="security_setting_lockdown_enabled"
|
||||||
android:title="@string/lockdown_settings_title"
|
android:title="@string/lockdown_settings_title"
|
||||||
android:summary="@string/lockdown_settings_summary" />
|
android:summary="@string/lockdown_settings_summary"
|
||||||
|
settings:controller="com.android.settings.security.LockdownButtonPreferenceController"/>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="security_setting_lock_screen_notif_work_header"
|
android:key="security_setting_lock_screen_notif_work_header"
|
||||||
|
|||||||
@@ -808,7 +808,6 @@ public class SettingsActivity extends SettingsDrawerActivity
|
|||||||
|| somethingChanged;
|
|| somethingChanged;
|
||||||
|
|
||||||
final boolean showDev = DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(this)
|
final boolean showDev = DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(this)
|
||||||
&& !um.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES)
|
|
||||||
&& !Utils.isMonkeyRunning();
|
&& !Utils.isMonkeyRunning();
|
||||||
|
|
||||||
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
somethingChanged = setTileEnabled(new ComponentName(packageName,
|
||||||
|
|||||||
@@ -42,6 +42,24 @@ public class LayoutPreference extends Preference {
|
|||||||
|
|
||||||
public LayoutPreference(Context context, AttributeSet attrs) {
|
public LayoutPreference(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
init(context, attrs, 0 /* defStyleAttr */);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LayoutPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
init(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LayoutPreference(Context context, int resource) {
|
||||||
|
this(context, LayoutInflater.from(context).inflate(resource, null, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LayoutPreference(Context context, View view) {
|
||||||
|
super(context);
|
||||||
|
setView(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Preference);
|
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Preference);
|
||||||
mAllowDividerAbove = TypedArrayUtils.getBoolean(a, R.styleable.Preference_allowDividerAbove,
|
mAllowDividerAbove = TypedArrayUtils.getBoolean(a, R.styleable.Preference_allowDividerAbove,
|
||||||
R.styleable.Preference_allowDividerAbove, false);
|
R.styleable.Preference_allowDividerAbove, false);
|
||||||
@@ -50,7 +68,7 @@ public class LayoutPreference extends Preference {
|
|||||||
a.recycle();
|
a.recycle();
|
||||||
|
|
||||||
a = context.obtainStyledAttributes(
|
a = context.obtainStyledAttributes(
|
||||||
attrs, com.android.internal.R.styleable.Preference, 0, 0);
|
attrs, com.android.internal.R.styleable.Preference, defStyleAttr, 0);
|
||||||
int layoutResource = a.getResourceId(com.android.internal.R.styleable.Preference_layout,
|
int layoutResource = a.getResourceId(com.android.internal.R.styleable.Preference_layout,
|
||||||
0);
|
0);
|
||||||
if (layoutResource == 0) {
|
if (layoutResource == 0) {
|
||||||
@@ -64,15 +82,6 @@ public class LayoutPreference extends Preference {
|
|||||||
setView(view);
|
setView(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LayoutPreference(Context context, int resource) {
|
|
||||||
this(context, LayoutInflater.from(context).inflate(resource, null, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
public LayoutPreference(Context context, View view) {
|
|
||||||
super(context);
|
|
||||||
setView(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setView(View view) {
|
private void setView(View view) {
|
||||||
setLayoutResource(R.layout.layout_preference_frame);
|
setLayoutResource(R.layout.layout_preference_frame);
|
||||||
final ViewGroup allDetails = view.findViewById(R.id.all_details);
|
final ViewGroup allDetails = view.findViewById(R.id.all_details);
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ import java.util.List;
|
|||||||
* Abstract class to consolidate utility between preference controllers and act as an interface
|
* Abstract class to consolidate utility between preference controllers and act as an interface
|
||||||
* for Slices. The abstract classes that inherit from this class will act as the direct interfaces
|
* for Slices. The abstract classes that inherit from this class will act as the direct interfaces
|
||||||
* for each type when plugging into Slices.
|
* for each type when plugging into Slices.
|
||||||
|
*
|
||||||
|
* TODO (b/73074893) Add Lifecycle Setting method.
|
||||||
*/
|
*/
|
||||||
public abstract class BasePreferenceController extends AbstractPreferenceController {
|
public abstract class BasePreferenceController extends AbstractPreferenceController {
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import com.android.settings.Settings;
|
|||||||
import com.android.settings.TestingSettings;
|
import com.android.settings.TestingSettings;
|
||||||
import com.android.settings.TetherSettings;
|
import com.android.settings.TetherSettings;
|
||||||
import com.android.settings.TrustedCredentialsSettings;
|
import com.android.settings.TrustedCredentialsSettings;
|
||||||
import com.android.settings.WifiCallingSettings;
|
import com.android.settings.wifi.calling.WifiCallingSettings;
|
||||||
import com.android.settings.accessibility.AccessibilitySettings;
|
import com.android.settings.accessibility.AccessibilitySettings;
|
||||||
import com.android.settings.accessibility.AccessibilitySettingsForSetupWizard;
|
import com.android.settings.accessibility.AccessibilitySettingsForSetupWizard;
|
||||||
import com.android.settings.accessibility.CaptionPropertiesFragment;
|
import com.android.settings.accessibility.CaptionPropertiesFragment;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class DashboardSummary extends InstrumentedFragment
|
|||||||
FocusListener, SuggestionControllerMixin.SuggestionControllerHost {
|
FocusListener, SuggestionControllerMixin.SuggestionControllerHost {
|
||||||
public static final boolean DEBUG = false;
|
public static final boolean DEBUG = false;
|
||||||
private static final boolean DEBUG_TIMING = false;
|
private static final boolean DEBUG_TIMING = false;
|
||||||
private static final int MAX_WAIT_MILLIS = 700;
|
private static final int MAX_WAIT_MILLIS = 3000;
|
||||||
private static final String TAG = "DashboardSummary";
|
private static final String TAG = "DashboardSummary";
|
||||||
|
|
||||||
private static final String EXTRA_SCROLL_POSITION = "scroll_position";
|
private static final String EXTRA_SCROLL_POSITION = "scroll_position";
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import com.android.settings.overlay.FeatureFactory;
|
|||||||
import com.android.settings.password.ScreenLockSuggestionActivity;
|
import com.android.settings.password.ScreenLockSuggestionActivity;
|
||||||
import com.android.settings.support.NewDeviceIntroSuggestionActivity;
|
import com.android.settings.support.NewDeviceIntroSuggestionActivity;
|
||||||
import com.android.settings.wallpaper.WallpaperSuggestionActivity;
|
import com.android.settings.wallpaper.WallpaperSuggestionActivity;
|
||||||
import com.android.settings.wifi.WifiCallingSuggestionActivity;
|
import com.android.settings.wifi.calling.WifiCallingSuggestionActivity;
|
||||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||||
import com.android.settingslib.drawer.Tile;
|
import com.android.settingslib.drawer.Tile;
|
||||||
import com.android.settingslib.suggestions.SuggestionControllerMixin;
|
import com.android.settingslib.suggestions.SuggestionControllerMixin;
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import android.app.Activity;
|
|||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.NetworkPolicyManager;
|
|
||||||
import android.net.NetworkTemplate;
|
import android.net.NetworkTemplate;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
@@ -28,6 +27,7 @@ import android.support.v7.preference.Preference;
|
|||||||
import android.support.v7.preference.PreferenceScreen;
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
import android.telephony.SubscriptionInfo;
|
import android.telephony.SubscriptionInfo;
|
||||||
import android.telephony.SubscriptionManager;
|
import android.telephony.SubscriptionManager;
|
||||||
|
import android.telephony.SubscriptionPlan;
|
||||||
import android.text.BidiFormatter;
|
import android.text.BidiFormatter;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
@@ -40,7 +40,6 @@ import android.view.MenuItem;
|
|||||||
|
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.SummaryPreference;
|
|
||||||
import com.android.settings.Utils;
|
import com.android.settings.Utils;
|
||||||
import com.android.settings.dashboard.SummaryLoader;
|
import com.android.settings.dashboard.SummaryLoader;
|
||||||
import com.android.settings.search.BaseSearchIndexProvider;
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
@@ -65,7 +64,6 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
|
|||||||
public static final String KEY_RESTRICT_BACKGROUND = "restrict_background";
|
public static final String KEY_RESTRICT_BACKGROUND = "restrict_background";
|
||||||
|
|
||||||
private static final String KEY_STATUS_HEADER = "status_header";
|
private static final String KEY_STATUS_HEADER = "status_header";
|
||||||
private static final String KEY_LIMIT_SUMMARY = "limit_summary";
|
|
||||||
|
|
||||||
// Mobile data keys
|
// Mobile data keys
|
||||||
public static final String KEY_MOBILE_USAGE_TITLE = "mobile_category";
|
public static final String KEY_MOBILE_USAGE_TITLE = "mobile_category";
|
||||||
@@ -77,13 +75,9 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
|
|||||||
public static final String KEY_WIFI_USAGE_TITLE = "wifi_category";
|
public static final String KEY_WIFI_USAGE_TITLE = "wifi_category";
|
||||||
public static final String KEY_WIFI_DATA_USAGE = "wifi_data_usage";
|
public static final String KEY_WIFI_DATA_USAGE = "wifi_data_usage";
|
||||||
|
|
||||||
private DataUsageController mDataUsageController;
|
private DataUsageSummaryPreference mSummaryPreference;
|
||||||
private DataUsageInfoController mDataInfoController;
|
private DataUsageSummaryPreferenceController mSummaryController;
|
||||||
private SummaryPreference mSummaryPreference;
|
|
||||||
private Preference mLimitPreference;
|
|
||||||
private NetworkTemplate mDefaultTemplate;
|
private NetworkTemplate mDefaultTemplate;
|
||||||
private int mDataUsageTemplate;
|
|
||||||
private NetworkPolicyEditor mPolicyEditor;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getHelpResource() {
|
public int getHelpResource() {
|
||||||
@@ -95,25 +89,20 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
|
|||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
|
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
NetworkPolicyManager policyManager = NetworkPolicyManager.from(context);
|
|
||||||
mPolicyEditor = new NetworkPolicyEditor(policyManager);
|
|
||||||
|
|
||||||
boolean hasMobileData = DataUsageUtils.hasMobileData(context);
|
boolean hasMobileData = DataUsageUtils.hasMobileData(context);
|
||||||
mDataUsageController = new DataUsageController(context);
|
|
||||||
mDataInfoController = new DataUsageInfoController();
|
|
||||||
|
|
||||||
int defaultSubId = DataUsageUtils.getDefaultSubscriptionId(context);
|
int defaultSubId = DataUsageUtils.getDefaultSubscriptionId(context);
|
||||||
if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
|
if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
|
||||||
hasMobileData = false;
|
hasMobileData = false;
|
||||||
}
|
}
|
||||||
mDefaultTemplate = DataUsageUtils.getDefaultTemplate(context, defaultSubId);
|
mDefaultTemplate = DataUsageUtils.getDefaultTemplate(context, defaultSubId);
|
||||||
mSummaryPreference = (SummaryPreference) findPreference(KEY_STATUS_HEADER);
|
mSummaryPreference = (DataUsageSummaryPreference) findPreference(KEY_STATUS_HEADER);
|
||||||
|
|
||||||
if (!hasMobileData || !isAdmin()) {
|
if (!hasMobileData || !isAdmin()) {
|
||||||
removePreference(KEY_RESTRICT_BACKGROUND);
|
removePreference(KEY_RESTRICT_BACKGROUND);
|
||||||
}
|
}
|
||||||
if (hasMobileData) {
|
if (hasMobileData) {
|
||||||
mLimitPreference = findPreference(KEY_LIMIT_SUMMARY);
|
|
||||||
List<SubscriptionInfo> subscriptions =
|
List<SubscriptionInfo> subscriptions =
|
||||||
services.mSubscriptionManager.getActiveSubscriptionInfoList();
|
services.mSubscriptionManager.getActiveSubscriptionInfoList();
|
||||||
if (subscriptions == null || subscriptions.size() == 0) {
|
if (subscriptions == null || subscriptions.size() == 0) {
|
||||||
@@ -127,10 +116,6 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
|
|||||||
addMobileSection(subInfo.getSubscriptionId());
|
addMobileSection(subInfo.getSubscriptionId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mSummaryPreference.setSelectable(true);
|
|
||||||
} else {
|
|
||||||
removePreference(KEY_LIMIT_SUMMARY);
|
|
||||||
mSummaryPreference.setSelectable(false);
|
|
||||||
}
|
}
|
||||||
boolean hasWifiRadio = DataUsageUtils.hasWifiRadio(context);
|
boolean hasWifiRadio = DataUsageUtils.hasWifiRadio(context);
|
||||||
if (hasWifiRadio) {
|
if (hasWifiRadio) {
|
||||||
@@ -139,10 +124,6 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
|
|||||||
if (hasEthernet(context)) {
|
if (hasEthernet(context)) {
|
||||||
addEthernetSection();
|
addEthernetSection();
|
||||||
}
|
}
|
||||||
mDataUsageTemplate = hasMobileData ? R.string.cell_data_template
|
|
||||||
: hasWifiRadio ? R.string.wifi_data_template
|
|
||||||
: R.string.ethernet_data_template;
|
|
||||||
|
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +170,11 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||||
return null;
|
final ArrayList<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||||
|
mSummaryController =
|
||||||
|
new DataUsageSummaryPreferenceController(context);
|
||||||
|
controllers.add(mSummaryController);
|
||||||
|
return controllers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMobileSection(int subId) {
|
private void addMobileSection(int subId) {
|
||||||
@@ -269,36 +254,6 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateState() {
|
private void updateState() {
|
||||||
DataUsageController.DataUsageInfo info = mDataUsageController.getDataUsageInfo(
|
|
||||||
mDefaultTemplate);
|
|
||||||
Context context = getContext();
|
|
||||||
mDataInfoController.updateDataLimit(info,
|
|
||||||
services.mPolicyEditor.getPolicy(mDefaultTemplate));
|
|
||||||
|
|
||||||
if (mSummaryPreference != null) {
|
|
||||||
mSummaryPreference.setTitle(
|
|
||||||
formatUsage(context, getString(mDataUsageTemplate), info.usageLevel));
|
|
||||||
final long limit = mDataInfoController.getSummaryLimit(info);
|
|
||||||
mSummaryPreference.setSummary(info.period);
|
|
||||||
if (limit <= 0) {
|
|
||||||
mSummaryPreference.setChartEnabled(false);
|
|
||||||
} else {
|
|
||||||
mSummaryPreference.setChartEnabled(true);
|
|
||||||
mSummaryPreference.setLabels(Formatter.formatFileSize(context, 0),
|
|
||||||
Formatter.formatFileSize(context, limit));
|
|
||||||
mSummaryPreference.setRatios(info.usageLevel / (float) limit, 0,
|
|
||||||
(limit - info.usageLevel) / (float) limit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mLimitPreference != null && (info.warningLevel > 0 || info.limitLevel > 0)) {
|
|
||||||
String warning = Formatter.formatFileSize(context, info.warningLevel);
|
|
||||||
String limit = Formatter.formatFileSize(context, info.limitLevel);
|
|
||||||
mLimitPreference.setSummary(getString(info.limitLevel <= 0 ? R.string.cell_warning_only
|
|
||||||
: R.string.cell_warning_and_limit, warning, limit));
|
|
||||||
} else if (mLimitPreference != null) {
|
|
||||||
mLimitPreference.setSummary(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
PreferenceScreen screen = getPreferenceScreen();
|
PreferenceScreen screen = getPreferenceScreen();
|
||||||
for (int i = 1; i < screen.getPreferenceCount(); i++) {
|
for (int i = 1; i < screen.getPreferenceCount(); i++) {
|
||||||
((TemplatePreferenceCategory) screen.getPreference(i)).pushTemplates(services);
|
((TemplatePreferenceCategory) screen.getPreference(i)).pushTemplates(services);
|
||||||
@@ -323,6 +278,7 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
|
|||||||
@Override
|
@Override
|
||||||
public void updateDataUsage() {
|
public void updateDataUsage() {
|
||||||
updateState();
|
updateState();
|
||||||
|
mSummaryController.updateState(mSummaryPreference);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SummaryProvider
|
private static class SummaryProvider
|
||||||
@@ -341,17 +297,39 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
|
|||||||
@Override
|
@Override
|
||||||
public void setListening(boolean listening) {
|
public void setListening(boolean listening) {
|
||||||
if (listening) {
|
if (listening) {
|
||||||
DataUsageController.DataUsageInfo info = mDataController.getDataUsageInfo();
|
|
||||||
String used;
|
|
||||||
if (info == null) {
|
|
||||||
used = Formatter.formatFileSize(mActivity, 0);
|
|
||||||
} else if (info.limitLevel <= 0) {
|
|
||||||
used = Formatter.formatFileSize(mActivity, info.usageLevel);
|
|
||||||
} else {
|
|
||||||
used = Utils.formatPercentage(info.usageLevel, info.limitLevel);
|
|
||||||
}
|
|
||||||
mSummaryLoader.setSummary(this,
|
mSummaryLoader.setSummary(this,
|
||||||
mActivity.getString(R.string.data_usage_summary_format, used));
|
mActivity.getString(R.string.data_usage_summary_format, formatUsedData()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatUsedData() {
|
||||||
|
SubscriptionManager subscriptionManager = (SubscriptionManager) mActivity
|
||||||
|
.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
|
||||||
|
int defaultSubId = subscriptionManager.getDefaultSubscriptionId();
|
||||||
|
if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
|
||||||
|
return formatFallbackData();
|
||||||
|
}
|
||||||
|
SubscriptionPlan dfltPlan = DataUsageSummaryPreferenceController
|
||||||
|
.getPrimaryPlan(subscriptionManager, defaultSubId);
|
||||||
|
if (dfltPlan == null) {
|
||||||
|
return formatFallbackData();
|
||||||
|
}
|
||||||
|
if (DataUsageSummaryPreferenceController.unlimited(dfltPlan.getDataLimitBytes())) {
|
||||||
|
return Formatter.formatFileSize(mActivity, dfltPlan.getDataUsageBytes());
|
||||||
|
} else {
|
||||||
|
return Utils.formatPercentage(dfltPlan.getDataUsageBytes(),
|
||||||
|
dfltPlan.getDataLimitBytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatFallbackData() {
|
||||||
|
DataUsageController.DataUsageInfo info = mDataController.getDataUsageInfo();
|
||||||
|
if (info == null) {
|
||||||
|
return Formatter.formatFileSize(mActivity, 0);
|
||||||
|
} else if (info.limitLevel <= 0) {
|
||||||
|
return Formatter.formatFileSize(mActivity, info.usageLevel);
|
||||||
|
} else {
|
||||||
|
return Utils.formatPercentage(info.usageLevel, info.limitLevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.datausage;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.support.v7.preference.PreferenceViewHolder;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.SummaryPreference;
|
||||||
|
import com.android.settingslib.utils.StringUtil;
|
||||||
|
|
||||||
|
import libcore.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a summary of data usage.
|
||||||
|
*/
|
||||||
|
public class DataUsageSummaryPreference extends SummaryPreference {
|
||||||
|
|
||||||
|
private int mNumPlans;
|
||||||
|
/** The ending time of the billing cycle in milliseconds since epoch. */
|
||||||
|
private long mCycleEndTimeMs;
|
||||||
|
/** The time of the last update in standard milliseconds since the epoch */
|
||||||
|
private long mSnapshotTimeMs;
|
||||||
|
/** Name of carrier, or null if not available */
|
||||||
|
private CharSequence mCarrierName;
|
||||||
|
private String mLimitInfoText;
|
||||||
|
private Intent mLaunchIntent;
|
||||||
|
|
||||||
|
public DataUsageSummaryPreference(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setLayoutResource(R.layout.data_usage_summary_preference);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLimitInfo(String text) {
|
||||||
|
if (!Objects.equal(text, mLimitInfoText)) {
|
||||||
|
mLimitInfoText = text;
|
||||||
|
notifyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsageInfo(long cycleEnd, long snapshotTime, CharSequence carrierName,
|
||||||
|
int numPlans, Intent launchIntent) {
|
||||||
|
mCycleEndTimeMs = cycleEnd;
|
||||||
|
mSnapshotTimeMs = snapshotTime;
|
||||||
|
mCarrierName = carrierName;
|
||||||
|
mNumPlans = numPlans;
|
||||||
|
mLaunchIntent = launchIntent;
|
||||||
|
notifyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||||
|
super.onBindViewHolder(holder);
|
||||||
|
|
||||||
|
TextView usageTitle = (TextView) holder.findViewById(R.id.usage_title);
|
||||||
|
usageTitle.setVisibility(mNumPlans > 1 ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
|
TextView cycleTime = (TextView) holder.findViewById(R.id.cycle_left_time);
|
||||||
|
cycleTime.setText(getContext().getString(R.string.cycle_left_time_text,
|
||||||
|
StringUtil.formatElapsedTime(getContext(),
|
||||||
|
mCycleEndTimeMs - System.currentTimeMillis(),false /* withSeconds */)));
|
||||||
|
|
||||||
|
TextView carrierInfo = (TextView) holder.findViewById(R.id.carrier_and_update);
|
||||||
|
setCarrierInfo(carrierInfo, mCarrierName, mSnapshotTimeMs);
|
||||||
|
|
||||||
|
Button launchButton = (Button) holder.findViewById(R.id.launch_mdp_app_button);
|
||||||
|
launchButton.setOnClickListener((view) -> {
|
||||||
|
getContext().sendBroadcast(mLaunchIntent);
|
||||||
|
});
|
||||||
|
if (mLaunchIntent != null) {
|
||||||
|
launchButton.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
launchButton.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextView limitInfo = (TextView) holder.findViewById(R.id.data_limits);
|
||||||
|
limitInfo.setVisibility(
|
||||||
|
mLimitInfoText == null || mLimitInfoText.isEmpty() ? View.GONE : View.VISIBLE);
|
||||||
|
limitInfo.setText(mLimitInfoText);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCarrierInfo(TextView carrierInfo, CharSequence carrierName, long updateAge) {
|
||||||
|
if (mNumPlans > 0 && updateAge >= 0L) {
|
||||||
|
carrierInfo.setVisibility(View.VISIBLE);
|
||||||
|
if (carrierName != null) {
|
||||||
|
carrierInfo.setText(getContext().getString(R.string.carrier_and_update_text,
|
||||||
|
carrierName, StringUtil.formatRelativeTime(
|
||||||
|
getContext(), updateAge, false /* withSeconds */)));
|
||||||
|
} else {
|
||||||
|
carrierInfo.setText(getContext().getString(R.string.no_carrier_update_text,
|
||||||
|
StringUtil.formatRelativeTime(
|
||||||
|
getContext(), updateAge, false /* withSeconds */)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
carrierInfo.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,286 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.datausage;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.NetworkPolicyManager;
|
||||||
|
import android.net.NetworkTemplate;
|
||||||
|
import android.support.annotation.VisibleForTesting;
|
||||||
|
import android.support.v7.preference.Preference;
|
||||||
|
import android.telephony.SubscriptionInfo;
|
||||||
|
import android.telephony.SubscriptionManager;
|
||||||
|
import android.telephony.SubscriptionPlan;
|
||||||
|
import android.text.BidiFormatter;
|
||||||
|
import android.text.Spannable;
|
||||||
|
import android.text.SpannableString;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.text.format.Formatter;
|
||||||
|
import android.text.style.RelativeSizeSpan;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.RecurrenceRule;
|
||||||
|
|
||||||
|
import com.android.internal.util.CollectionUtils;
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
import com.android.settingslib.NetworkPolicyEditor;
|
||||||
|
import com.android.settingslib.net.DataUsageController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the controller for the top of the data usage screen that retrieves carrier data from the
|
||||||
|
* new subscriptions framework API if available. The controller reads subscription information from
|
||||||
|
* the framework and falls back to legacy usage data if none are available.
|
||||||
|
*/
|
||||||
|
public class DataUsageSummaryPreferenceController extends BasePreferenceController {
|
||||||
|
|
||||||
|
private static final String TAG = "DataUsageController";
|
||||||
|
private static final String KEY = "status_header";
|
||||||
|
private static final long PETA = 1000000000000000L;
|
||||||
|
private static final float RELATIVE_SIZE_LARGE = 1.25f * 1.25f; // (1/0.8)^2
|
||||||
|
private static final float RELATIVE_SIZE_SMALL = 1.0f / RELATIVE_SIZE_LARGE; // 0.8^2
|
||||||
|
|
||||||
|
private final DataUsageController mDataUsageController;
|
||||||
|
private final DataUsageInfoController mDataInfoController;
|
||||||
|
private final NetworkTemplate mDefaultTemplate;
|
||||||
|
private final NetworkPolicyEditor mPolicyEditor;
|
||||||
|
private final int mDataUsageTemplate;
|
||||||
|
private final boolean mHasMobileData;
|
||||||
|
private final SubscriptionManager mSubscriptionManager;
|
||||||
|
|
||||||
|
/** Name of the carrier, or null if not available */
|
||||||
|
private CharSequence mCarrierName;
|
||||||
|
|
||||||
|
/** The number of registered plans, [0,N] */
|
||||||
|
private int mDataplanCount;
|
||||||
|
|
||||||
|
/** The time of the last update in milliseconds since the epoch, or -1 if unknown */
|
||||||
|
private long mSnapshotTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the first registered plan if one exists or the size of the warning if it is set.
|
||||||
|
* -1 if no information is available.
|
||||||
|
*/
|
||||||
|
private long mDataplanSize;
|
||||||
|
/** The number of bytes used since the start of the cycle. */
|
||||||
|
private long mDataplanUse;
|
||||||
|
/** The starting time of the billing cycle in ms since the epoch */
|
||||||
|
private long mCycleStart;
|
||||||
|
/** The ending time of the billing cycle in ms since the epoch */
|
||||||
|
private long mCycleEnd;
|
||||||
|
|
||||||
|
private Intent mManageSubscriptionIntent;
|
||||||
|
|
||||||
|
public DataUsageSummaryPreferenceController(Context context) {
|
||||||
|
super(context, KEY);
|
||||||
|
|
||||||
|
final int defaultSubId = DataUsageUtils.getDefaultSubscriptionId(context);
|
||||||
|
mDefaultTemplate = DataUsageUtils.getDefaultTemplate(context, defaultSubId);
|
||||||
|
NetworkPolicyManager policyManager = NetworkPolicyManager.from(context);
|
||||||
|
mPolicyEditor = new NetworkPolicyEditor(policyManager);
|
||||||
|
|
||||||
|
mHasMobileData = DataUsageUtils.hasMobileData(context)
|
||||||
|
&& defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||||
|
|
||||||
|
mDataUsageController = new DataUsageController(context);
|
||||||
|
mDataInfoController = new DataUsageInfoController();
|
||||||
|
|
||||||
|
if (mHasMobileData) {
|
||||||
|
mDataUsageTemplate = R.string.cell_data_template;
|
||||||
|
} else if (DataUsageUtils.hasWifiRadio(context)) {
|
||||||
|
mDataUsageTemplate = R.string.wifi_data_template;
|
||||||
|
} else {
|
||||||
|
mDataUsageTemplate = R.string.ethernet_data_template;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSubscriptionManager = (SubscriptionManager)
|
||||||
|
mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
DataUsageSummaryPreferenceController(
|
||||||
|
Context context,
|
||||||
|
DataUsageController dataUsageController,
|
||||||
|
DataUsageInfoController dataInfoController,
|
||||||
|
NetworkTemplate defaultTemplate,
|
||||||
|
NetworkPolicyEditor policyEditor,
|
||||||
|
int dataUsageTemplate,
|
||||||
|
boolean hasMobileData,
|
||||||
|
SubscriptionManager subscriptionManager) {
|
||||||
|
super(context, KEY);
|
||||||
|
mDataUsageController = dataUsageController;
|
||||||
|
mDataInfoController = dataInfoController;
|
||||||
|
mDefaultTemplate = defaultTemplate;
|
||||||
|
mPolicyEditor = policyEditor;
|
||||||
|
mDataUsageTemplate = dataUsageTemplate;
|
||||||
|
mHasMobileData = hasMobileData;
|
||||||
|
mSubscriptionManager = subscriptionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void setPlanValues(int dataPlanCount, long dataPlanSize, long dataPlanUse) {
|
||||||
|
mDataplanCount = dataPlanCount;
|
||||||
|
mDataplanSize = dataPlanSize;
|
||||||
|
mDataplanUse = dataPlanUse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void setCarrierValues(String carrierName, long snapshotTime, long cycleEnd, Intent intent) {
|
||||||
|
mCarrierName = carrierName;
|
||||||
|
mSnapshotTime = snapshotTime;
|
||||||
|
mCycleEnd = cycleEnd;
|
||||||
|
mManageSubscriptionIntent = intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAvailabilityStatus() {
|
||||||
|
return AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateState(Preference preference) {
|
||||||
|
DataUsageSummaryPreference summaryPreference = (DataUsageSummaryPreference) preference;
|
||||||
|
DataUsageController.DataUsageInfo info = mDataUsageController.getDataUsageInfo(
|
||||||
|
mDefaultTemplate);
|
||||||
|
|
||||||
|
mDataInfoController.updateDataLimit(info, mPolicyEditor.getPolicy(mDefaultTemplate));
|
||||||
|
|
||||||
|
if (mSubscriptionManager != null) {
|
||||||
|
refreshDataplanInfo(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDataplanCount == 0 && (info.warningLevel > 0 || info.limitLevel > 0)) {
|
||||||
|
final String warning = Formatter.formatFileSize(mContext, info.warningLevel);
|
||||||
|
final String limit = Formatter.formatFileSize(mContext, info.limitLevel);
|
||||||
|
summaryPreference.setLimitInfo(mContext.getString(info.limitLevel <= 0
|
||||||
|
? R.string.cell_warning_only
|
||||||
|
: R.string.cell_warning_and_limit, warning, limit));
|
||||||
|
} else {
|
||||||
|
summaryPreference.setLimitInfo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final StringBuilder title = new StringBuilder();
|
||||||
|
if (mHasMobileData) {
|
||||||
|
title.append(formatUsage(mContext, mContext.getString(R.string.data_used),
|
||||||
|
mDataplanUse));
|
||||||
|
if (mDataplanCount >= 0 && mDataplanSize > 0L) {
|
||||||
|
title.append(formatUsage(mContext, mContext.getString(R.string.data_remaining),
|
||||||
|
mDataplanSize - mDataplanUse));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
title.append(formatUsage(mContext, mContext.getString(mDataUsageTemplate),
|
||||||
|
mDataplanUse));
|
||||||
|
}
|
||||||
|
summaryPreference.setTitle(title.toString());
|
||||||
|
|
||||||
|
if (mDataplanSize <= 0) {
|
||||||
|
summaryPreference.setChartEnabled(false);
|
||||||
|
} else {
|
||||||
|
summaryPreference.setChartEnabled(true);
|
||||||
|
summaryPreference.setLabels(Formatter.formatFileSize(mContext, 0 /* sizeBytes */),
|
||||||
|
Formatter.formatFileSize(mContext, mDataplanSize));
|
||||||
|
summaryPreference.setRatios(mDataplanUse / (float) mDataplanSize, 0 /* middle */,
|
||||||
|
(mDataplanSize - mDataplanUse) / (float) mDataplanSize);
|
||||||
|
}
|
||||||
|
summaryPreference.setUsageInfo(mCycleEnd, mSnapshotTime, mCarrierName,
|
||||||
|
mDataplanCount, mManageSubscriptionIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(b/70950124) add test for this method once the robolectric shadow run script is
|
||||||
|
// completed (b/3526807)
|
||||||
|
private void refreshDataplanInfo(DataUsageController.DataUsageInfo info) {
|
||||||
|
// reset data before overwriting
|
||||||
|
mCarrierName = null;
|
||||||
|
mDataplanCount = 0;
|
||||||
|
mDataplanSize = mDataInfoController.getSummaryLimit(info);
|
||||||
|
mDataplanUse = info.usageLevel;
|
||||||
|
mCycleStart = info.cycleStart;
|
||||||
|
mCycleEnd = info.cycleEnd;
|
||||||
|
mSnapshotTime = -1L;
|
||||||
|
|
||||||
|
final int defaultSubId = SubscriptionManager.getDefaultSubscriptionId();
|
||||||
|
final SubscriptionInfo subInfo = mSubscriptionManager.getDefaultDataSubscriptionInfo();
|
||||||
|
if (subInfo != null && mHasMobileData) {
|
||||||
|
mCarrierName = subInfo.getCarrierName();
|
||||||
|
List<SubscriptionPlan> plans = mSubscriptionManager.getSubscriptionPlans(defaultSubId);
|
||||||
|
final SubscriptionPlan primaryPlan = getPrimaryPlan(mSubscriptionManager, defaultSubId);
|
||||||
|
if (primaryPlan != null) {
|
||||||
|
mDataplanCount = plans.size();
|
||||||
|
mDataplanSize = primaryPlan.getDataLimitBytes();
|
||||||
|
if (unlimited(mDataplanSize)) {
|
||||||
|
mDataplanSize = 0L;
|
||||||
|
}
|
||||||
|
mDataplanUse = primaryPlan.getDataUsageBytes();
|
||||||
|
|
||||||
|
RecurrenceRule rule = primaryPlan.getCycleRule();
|
||||||
|
if (rule != null && rule.start != null && rule.end != null) {
|
||||||
|
mCycleStart = rule.start.toEpochSecond() * 1000L;
|
||||||
|
mCycleEnd = rule.end.toEpochSecond() * 1000L;
|
||||||
|
}
|
||||||
|
mSnapshotTime = System.currentTimeMillis() - primaryPlan.getDataUsageTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mManageSubscriptionIntent =
|
||||||
|
mSubscriptionManager.createManageSubscriptionIntent(defaultSubId);
|
||||||
|
Log.i(TAG, "Have " + mDataplanCount + " plans, dflt sub-id " + defaultSubId
|
||||||
|
+ ", intent " + mManageSubscriptionIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SubscriptionPlan getPrimaryPlan(SubscriptionManager subManager, int primaryId) {
|
||||||
|
List<SubscriptionPlan> plans = subManager.getSubscriptionPlans(primaryId);
|
||||||
|
if (CollectionUtils.isEmpty(plans)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// First plan in the list is the primary plan
|
||||||
|
SubscriptionPlan plan = plans.get(0);
|
||||||
|
return plan.getDataLimitBytes() > 0
|
||||||
|
&& saneSize(plan.getDataUsageBytes())
|
||||||
|
&& plan.getCycleRule() != null ? plan : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean saneSize(long value) {
|
||||||
|
return value >= 0L && value < PETA;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean unlimited(long size) {
|
||||||
|
return size == SubscriptionPlan.BYTES_UNLIMITED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
private static CharSequence formatUsage(Context context, String template, long usageLevel) {
|
||||||
|
final int FLAGS = Spannable.SPAN_INCLUSIVE_INCLUSIVE;
|
||||||
|
|
||||||
|
final Formatter.BytesResult usedResult = Formatter.formatBytes(context.getResources(),
|
||||||
|
usageLevel, Formatter.FLAG_CALCULATE_ROUNDED);
|
||||||
|
final SpannableString enlargedValue = new SpannableString(usedResult.value);
|
||||||
|
enlargedValue.setSpan(
|
||||||
|
new RelativeSizeSpan(RELATIVE_SIZE_LARGE), 0, enlargedValue.length(), FLAGS);
|
||||||
|
|
||||||
|
final SpannableString amountTemplate = new SpannableString(
|
||||||
|
context.getString(com.android.internal.R.string.fileSizeSuffix)
|
||||||
|
.replace("%1$s", "^1").replace("%2$s", "^2"));
|
||||||
|
final CharSequence formattedUsage = TextUtils.expandTemplate(amountTemplate,
|
||||||
|
enlargedValue, usedResult.units);
|
||||||
|
|
||||||
|
final SpannableString fullTemplate = new SpannableString(template);
|
||||||
|
fullTemplate.setSpan(
|
||||||
|
new RelativeSizeSpan(RELATIVE_SIZE_SMALL), 0, fullTemplate.length(), FLAGS);
|
||||||
|
return TextUtils.expandTemplate(fullTemplate,
|
||||||
|
BidiFormatter.getInstance().unicodeWrap(formattedUsage.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import static com.android.settings.bluetooth.Utils.getLocalBtManager;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
@@ -126,6 +127,16 @@ public class MyDeviceInfoFragment extends DashboardFragment {
|
|||||||
return controllers;
|
return controllers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
final BuildNumberPreferenceController buildNumberPreferenceController =
|
||||||
|
getPreferenceController(BuildNumberPreferenceController.class);
|
||||||
|
if (buildNumberPreferenceController.onActivityResult(requestCode, resultCode, data)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
}
|
||||||
|
|
||||||
private void initHeader() {
|
private void initHeader() {
|
||||||
// TODO: Migrate into its own controller.
|
// TODO: Migrate into its own controller.
|
||||||
final LayoutPreference headerPreference =
|
final LayoutPreference headerPreference =
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class BatteryAppListPreferenceController extends AbstractPreferenceController
|
public class BatteryAppListPreferenceController extends AbstractPreferenceController
|
||||||
implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy {
|
implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnDestroy {
|
||||||
private static final boolean USE_FAKE_DATA = true;
|
@VisibleForTesting
|
||||||
|
static final boolean USE_FAKE_DATA = false;
|
||||||
private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 10;
|
private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 10;
|
||||||
private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
|
private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
|
||||||
private static final int STATS_TYPE = BatteryStats.STATS_SINCE_CHARGED;
|
private static final int STATS_TYPE = BatteryStats.STATS_SINCE_CHARGED;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import com.android.settings.Utils;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this broadcastReceiver to listen to the battery change, and it will invoke
|
* Use this broadcastReceiver to listen to the battery change, and it will invoke
|
||||||
* {@link OnBatteryChangedListener} if any of the followings has been changed:
|
* {@link OnBatteryChangedListener} if any of the following has been changed:
|
||||||
*
|
*
|
||||||
* 1. Battery level(e.g. 100%->99%)
|
* 1. Battery level(e.g. 100%->99%)
|
||||||
* 2. Battery status(e.g. plugged->unplugged)
|
* 2. Battery status(e.g. plugged->unplugged)
|
||||||
@@ -35,7 +35,14 @@ import com.android.settings.Utils;
|
|||||||
*/
|
*/
|
||||||
public class BatteryBroadcastReceiver extends BroadcastReceiver {
|
public class BatteryBroadcastReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
interface OnBatteryChangedListener {
|
/**
|
||||||
|
* Callback when the following has been changed:
|
||||||
|
*
|
||||||
|
* Battery level(e.g. 100%->99%)
|
||||||
|
* Battery status(e.g. plugged->unplugged)
|
||||||
|
* Battery saver(e.g. off->on)
|
||||||
|
*/
|
||||||
|
public interface OnBatteryChangedListener {
|
||||||
void onBatteryChanged();
|
void onBatteryChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class BatterySaverReceiver extends BroadcastReceiver {
|
|||||||
mBatterySaverListener = lsn;
|
mBatterySaverListener = lsn;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BatterySaverListener {
|
public interface BatterySaverListener {
|
||||||
void onPowerSaveModeChanged();
|
void onPowerSaveModeChanged();
|
||||||
void onBatteryChanged(boolean pluggedIn);
|
void onBatteryChanged(boolean pluggedIn);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,21 @@
|
|||||||
|
|
||||||
package com.android.settings.fuelgauge;
|
package com.android.settings.fuelgauge;
|
||||||
|
|
||||||
|
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
|
||||||
|
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
|
||||||
|
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
|
||||||
|
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
|
||||||
|
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
|
||||||
|
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
|
||||||
|
|
||||||
import android.app.usage.UsageStatsManager;
|
import android.app.usage.UsageStatsManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.preference.ListPreference;
|
||||||
import android.support.v7.preference.Preference;
|
import android.support.v7.preference.Preference;
|
||||||
import android.support.v7.preference.Preference.OnPreferenceClickListener;
|
import android.support.v7.preference.Preference.OnPreferenceClickListener;
|
||||||
import android.support.v7.preference.PreferenceGroup;
|
import android.support.v7.preference.PreferenceGroup;
|
||||||
@@ -29,10 +38,22 @@ import android.support.v7.preference.PreferenceGroup;
|
|||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.SettingsPreferenceFragment;
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
|
import com.android.settings.widget.RadioButtonPreference;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class InactiveApps extends SettingsPreferenceFragment implements OnPreferenceClickListener {
|
public class InactiveApps extends SettingsPreferenceFragment
|
||||||
|
implements Preference.OnPreferenceChangeListener {
|
||||||
|
|
||||||
|
private static final CharSequence[] SETTABLE_BUCKETS_NAMES =
|
||||||
|
{"ACTIVE", "WORKING_SET", "FREQUENT", "RARE"};
|
||||||
|
|
||||||
|
private static final CharSequence[] SETTABLE_BUCKETS_VALUES = {
|
||||||
|
Integer.toString(STANDBY_BUCKET_ACTIVE),
|
||||||
|
Integer.toString(STANDBY_BUCKET_WORKING_SET),
|
||||||
|
Integer.toString(STANDBY_BUCKET_FREQUENT),
|
||||||
|
Integer.toString(STANDBY_BUCKET_RARE)
|
||||||
|
};
|
||||||
|
|
||||||
private UsageStatsManager mUsageStats;
|
private UsageStatsManager mUsageStats;
|
||||||
|
|
||||||
@@ -68,29 +89,51 @@ public class InactiveApps extends SettingsPreferenceFragment implements OnPrefer
|
|||||||
List<ResolveInfo> apps = pm.queryIntentActivities(launcherIntent, 0);
|
List<ResolveInfo> apps = pm.queryIntentActivities(launcherIntent, 0);
|
||||||
for (ResolveInfo app : apps) {
|
for (ResolveInfo app : apps) {
|
||||||
String packageName = app.activityInfo.applicationInfo.packageName;
|
String packageName = app.activityInfo.applicationInfo.packageName;
|
||||||
Preference p = new Preference(getPrefContext());
|
ListPreference p = new ListPreference(getPrefContext());
|
||||||
p.setTitle(app.loadLabel(pm));
|
p.setTitle(app.loadLabel(pm));
|
||||||
p.setIcon(app.loadIcon(pm));
|
p.setIcon(app.loadIcon(pm));
|
||||||
p.setKey(packageName);
|
p.setKey(packageName);
|
||||||
|
p.setEntries(SETTABLE_BUCKETS_NAMES);
|
||||||
|
p.setEntryValues(SETTABLE_BUCKETS_VALUES);
|
||||||
updateSummary(p);
|
updateSummary(p);
|
||||||
p.setOnPreferenceClickListener(this);
|
p.setOnPreferenceChangeListener(this);
|
||||||
|
|
||||||
screen.addPreference(p);
|
screen.addPreference(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSummary(Preference p) {
|
static String bucketToName(int bucket) {
|
||||||
boolean inactive = mUsageStats.isAppInactive(p.getKey());
|
switch (bucket) {
|
||||||
p.setSummary(inactive
|
case STANDBY_BUCKET_EXEMPTED: return "EXEMPTED";
|
||||||
? R.string.inactive_app_inactive_summary
|
case STANDBY_BUCKET_ACTIVE: return "ACTIVE";
|
||||||
: R.string.inactive_app_active_summary);
|
case STANDBY_BUCKET_WORKING_SET: return "WORKING_SET";
|
||||||
|
case STANDBY_BUCKET_FREQUENT: return "FREQUENT";
|
||||||
|
case STANDBY_BUCKET_RARE: return "RARE";
|
||||||
|
case STANDBY_BUCKET_NEVER: return "NEVER";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSummary(ListPreference p) {
|
||||||
|
final Resources res = getActivity().getResources();
|
||||||
|
final int appBucket = mUsageStats.getAppStandbyBucket(p.getKey());
|
||||||
|
final String bucketName = bucketToName(appBucket);
|
||||||
|
p.setSummary(res.getString(R.string.standby_bucket_summary, bucketName));
|
||||||
|
// Buckets outside of the range of the dynamic ones are only used for special
|
||||||
|
// purposes and can either not be changed out of, or might have undesirable
|
||||||
|
// side-effects in combination with other assumptions.
|
||||||
|
final boolean changeable = appBucket >= STANDBY_BUCKET_ACTIVE
|
||||||
|
&& appBucket <= STANDBY_BUCKET_RARE;
|
||||||
|
if (changeable) {
|
||||||
|
p.setValue(Integer.toString(appBucket));
|
||||||
|
}
|
||||||
|
p.setEnabled(changeable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
String packageName = preference.getKey();
|
mUsageStats.setAppStandbyBucket(preference.getKey(), Integer.parseInt((String) newValue));
|
||||||
mUsageStats.setAppInactive(packageName, !mUsageStats.isAppInactive(packageName));
|
updateSummary((ListPreference) preference);
|
||||||
updateSummary(preference);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.fuelgauge.batterysaver;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.support.annotation.VisibleForTesting;
|
||||||
|
import android.support.v7.preference.Preference;
|
||||||
|
|
||||||
|
import com.android.settings.fuelgauge.BatteryBroadcastReceiver;
|
||||||
|
import com.android.settings.fuelgauge.BatterySaverReceiver;
|
||||||
|
import com.android.settings.widget.TwoStateButtonPreferenceController;
|
||||||
|
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||||
|
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||||
|
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||||
|
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller to update the battery saver button
|
||||||
|
*/
|
||||||
|
public class BatterySaverButtonPreferenceController extends
|
||||||
|
TwoStateButtonPreferenceController implements
|
||||||
|
LifecycleObserver, OnStart, OnStop, BatterySaverReceiver.BatterySaverListener {
|
||||||
|
private static final String KEY = "battery_saver_button_container";
|
||||||
|
private BatterySaverReceiver mBatterySaverReceiver;
|
||||||
|
@VisibleForTesting
|
||||||
|
PowerManager mPowerManager;
|
||||||
|
|
||||||
|
public BatterySaverButtonPreferenceController(Context context, Lifecycle lifecycle) {
|
||||||
|
super(context, KEY);
|
||||||
|
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||||
|
mBatterySaverReceiver = new BatterySaverReceiver(context);
|
||||||
|
mBatterySaverReceiver.setBatterySaverListener(this);
|
||||||
|
if (lifecycle != null) {
|
||||||
|
lifecycle.addObserver(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
mBatterySaverReceiver.setListening(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
mBatterySaverReceiver.setListening(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateState(Preference preference) {
|
||||||
|
super.updateState(preference);
|
||||||
|
setButtonVisibility(!mPowerManager.isPowerSaveMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAvailabilityStatus() {
|
||||||
|
return AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onButtonClicked(boolean stateOn) {
|
||||||
|
mPowerManager.setPowerSaveMode(stateOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPowerSaveModeChanged() {
|
||||||
|
setButtonVisibility(!mPowerManager.isPowerSaveMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBatteryChanged(boolean pluggedIn) {
|
||||||
|
setButtonEnabled(!pluggedIn);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -78,6 +78,7 @@ public class BatterySaverSettings extends DashboardFragment {
|
|||||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||||
controllers.add(new AutoBatterySaverPreferenceController(context));
|
controllers.add(new AutoBatterySaverPreferenceController(context));
|
||||||
controllers.add(new AutoBatterySeekBarPreferenceController(context, lifecycle));
|
controllers.add(new AutoBatterySeekBarPreferenceController(context, lifecycle));
|
||||||
|
controllers.add(new BatterySaverButtonPreferenceController(context, lifecycle));
|
||||||
return controllers;
|
return controllers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import com.android.settings.R;
|
|||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settings.search.SearchFeatureProvider;
|
import com.android.settings.search.SearchFeatureProvider;
|
||||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||||
|
import com.android.settingslib.core.lifecycle.ObservableFragment;
|
||||||
import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment;
|
import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment;
|
||||||
import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
|
import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
|
||||||
|
|
||||||
@@ -41,6 +42,10 @@ public class SearchMenuController implements LifecycleObserver, OnCreateOptionsM
|
|||||||
host.getLifecycle().addObserver(new SearchMenuController(host));
|
host.getLifecycle().addObserver(new SearchMenuController(host));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void init(@NonNull ObservableFragment host) {
|
||||||
|
host.getLifecycle().addObserver(new SearchMenuController(host));
|
||||||
|
}
|
||||||
|
|
||||||
private SearchMenuController(@NonNull Fragment host) {
|
private SearchMenuController(@NonNull Fragment host) {
|
||||||
mHost = host;
|
mHost = host;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ public class VisiblePatternProfilePreferenceController extends TogglePreferenceC
|
|||||||
|
|
||||||
private Preference mPreference;
|
private Preference mPreference;
|
||||||
|
|
||||||
|
public VisiblePatternProfilePreferenceController(Context context) {
|
||||||
|
this(context, null /* lifecycle */);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO (b/73074893) Replace this constructor without Lifecycle using setter method instead.
|
||||||
public VisiblePatternProfilePreferenceController(Context context, Lifecycle lifecycle) {
|
public VisiblePatternProfilePreferenceController(Context context, Lifecycle lifecycle) {
|
||||||
super(context, KEY_VISIBLE_PATTERN_PROFILE);
|
super(context, KEY_VISIBLE_PATTERN_PROFILE);
|
||||||
mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import android.view.MenuInflater;
|
|||||||
|
|
||||||
import com.android.settingslib.HelpUtils;
|
import com.android.settingslib.HelpUtils;
|
||||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||||
|
import com.android.settingslib.core.lifecycle.ObservableFragment;
|
||||||
import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment;
|
import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment;
|
||||||
import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
|
import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
|
||||||
|
|
||||||
@@ -41,6 +42,10 @@ public class HelpMenuController implements LifecycleObserver, OnCreateOptionsMen
|
|||||||
host.getLifecycle().addObserver(new HelpMenuController(host));
|
host.getLifecycle().addObserver(new HelpMenuController(host));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void init(@NonNull ObservableFragment host) {
|
||||||
|
host.getLifecycle().addObserver(new HelpMenuController(host));
|
||||||
|
}
|
||||||
|
|
||||||
private HelpMenuController(@NonNull Fragment host) {
|
private HelpMenuController(@NonNull Fragment host) {
|
||||||
mHost = host;
|
mHost = host;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ public class MasterCheckBoxPreference extends TwoTargetPreference {
|
|||||||
if (mCheckBox != null) {
|
if (mCheckBox != null) {
|
||||||
mCheckBox.setContentDescription(getTitle());
|
mCheckBox.setContentDescription(getTitle());
|
||||||
mCheckBox.setChecked(mChecked);
|
mCheckBox.setChecked(mChecked);
|
||||||
|
mCheckBox.setEnabled(mEnableCheckBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.widget;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.support.v4.content.res.TypedArrayUtils;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.applications.LayoutPreference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preference that presents a button with two states(On vs Off)
|
||||||
|
*/
|
||||||
|
public class TwoStateButtonPreference extends LayoutPreference {
|
||||||
|
public TwoStateButtonPreference(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs, TypedArrayUtils.getAttr(
|
||||||
|
context, R.attr.twoStateButtonPreferenceStyle, android.R.attr.preferenceStyle));
|
||||||
|
|
||||||
|
if (attrs != null) {
|
||||||
|
final TypedArray styledAttrs = context.obtainStyledAttributes(attrs,
|
||||||
|
R.styleable.TwoStateButtonPreference);
|
||||||
|
final int textOnId = styledAttrs.getResourceId(
|
||||||
|
R.styleable.TwoStateButtonPreference_textOn,
|
||||||
|
R.string.summary_placeholder);
|
||||||
|
final int textOffId = styledAttrs.getResourceId(
|
||||||
|
R.styleable.TwoStateButtonPreference_textOff,
|
||||||
|
R.string.summary_placeholder);
|
||||||
|
styledAttrs.recycle();
|
||||||
|
|
||||||
|
final Button buttonOn = getStateOnButton();
|
||||||
|
buttonOn.setText(textOnId);
|
||||||
|
final Button buttonOff = getStateOffButton();
|
||||||
|
buttonOff.setText(textOffId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Button getStateOnButton() {
|
||||||
|
return findViewById(R.id.state_on_button);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Button getStateOffButton() {
|
||||||
|
return findViewById(R.id.state_off_button);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.widget;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller to update the button with two states(On vs Off).
|
||||||
|
*/
|
||||||
|
public abstract class TwoStateButtonPreferenceController extends BasePreferenceController
|
||||||
|
implements View.OnClickListener {
|
||||||
|
private Button mButtonOn;
|
||||||
|
private Button mButtonOff;
|
||||||
|
|
||||||
|
public TwoStateButtonPreferenceController(Context context, String key) {
|
||||||
|
super(context, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void displayPreference(PreferenceScreen screen) {
|
||||||
|
super.displayPreference(screen);
|
||||||
|
final TwoStateButtonPreference preference =
|
||||||
|
(TwoStateButtonPreference) screen.findPreference(getPreferenceKey());
|
||||||
|
mButtonOn = preference.getStateOnButton();
|
||||||
|
mButtonOn.setOnClickListener(this);
|
||||||
|
mButtonOff = preference.getStateOffButton();
|
||||||
|
mButtonOff.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setButtonVisibility(boolean stateOn) {
|
||||||
|
if (stateOn) {
|
||||||
|
mButtonOff.setVisibility(View.GONE);
|
||||||
|
mButtonOn.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
mButtonOff.setVisibility(View.VISIBLE);
|
||||||
|
mButtonOn.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setButtonEnabled(boolean enabled) {
|
||||||
|
mButtonOn.setEnabled(enabled);
|
||||||
|
mButtonOff.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
final boolean stateOn = v.getId() == R.id.state_on_button;
|
||||||
|
onButtonClicked(stateOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback when button is clicked
|
||||||
|
*
|
||||||
|
* @param stateOn {@code true} if stateOn button is clicked, otherwise it means stateOff
|
||||||
|
* button is clicked
|
||||||
|
*/
|
||||||
|
public abstract void onButtonClicked(boolean stateOn);
|
||||||
|
}
|
||||||
@@ -14,11 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings;
|
package com.android.settings.wifi.calling;
|
||||||
|
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.app.FragmentManager;
|
import android.app.FragmentManager;
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v13.app.FragmentPagerAdapter;
|
import android.support.v13.app.FragmentPagerAdapter;
|
||||||
import android.telephony.SubscriptionInfo;
|
import android.telephony.SubscriptionInfo;
|
||||||
@@ -28,9 +27,13 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.android.ims.ImsConfig;
|
|
||||||
import com.android.ims.ImsManager;
|
import com.android.ims.ImsManager;
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.core.InstrumentedFragment;
|
||||||
|
import com.android.settings.search.actionbar.SearchMenuController;
|
||||||
|
import com.android.settings.support.actionbar.HelpMenuController;
|
||||||
|
import com.android.settings.support.actionbar.HelpResourceProvider;
|
||||||
import com.android.settings.widget.RtlCompatibleViewPager;
|
import com.android.settings.widget.RtlCompatibleViewPager;
|
||||||
import com.android.settings.widget.SlidingTabLayout;
|
import com.android.settings.widget.SlidingTabLayout;
|
||||||
|
|
||||||
@@ -40,7 +43,7 @@ import java.util.List;
|
|||||||
* "Wi-Fi Calling settings" screen. This is the container fragment which holds
|
* "Wi-Fi Calling settings" screen. This is the container fragment which holds
|
||||||
* {@link WifiCallingSettingsForSub} fragments.
|
* {@link WifiCallingSettingsForSub} fragments.
|
||||||
*/
|
*/
|
||||||
public class WifiCallingSettings extends SettingsPreferenceFragment {
|
public class WifiCallingSettings extends InstrumentedFragment implements HelpResourceProvider {
|
||||||
private static final String TAG = "WifiCallingSettings";
|
private static final String TAG = "WifiCallingSettings";
|
||||||
private List<SubscriptionInfo> mSil;
|
private List<SubscriptionInfo> mSil;
|
||||||
|
|
||||||
@@ -71,6 +74,10 @@ public class WifiCallingSettings extends SettingsPreferenceFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle icicle) {
|
public void onCreate(Bundle icicle) {
|
||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
|
setHasOptionsMenu(true);
|
||||||
|
SearchMenuController.init(this /* host */);
|
||||||
|
HelpMenuController.init(this /* host */);
|
||||||
|
|
||||||
// TODO: besides in onCreate, we should also update subList when SIM / Sub status
|
// TODO: besides in onCreate, we should also update subList when SIM / Sub status
|
||||||
// changes.
|
// changes.
|
||||||
updateSubList();
|
updateSubList();
|
||||||
@@ -87,6 +94,11 @@ public class WifiCallingSettings extends SettingsPreferenceFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHelpResource() {
|
||||||
|
return R.string.help_uri_wifi_calling;
|
||||||
|
}
|
||||||
|
|
||||||
private final class WifiCallingViewPagerAdapter extends FragmentPagerAdapter {
|
private final class WifiCallingViewPagerAdapter extends FragmentPagerAdapter {
|
||||||
private final RtlCompatibleViewPager mViewPager;
|
private final RtlCompatibleViewPager mViewPager;
|
||||||
|
|
||||||
@@ -105,6 +117,7 @@ public class WifiCallingSettings extends SettingsPreferenceFragment {
|
|||||||
public Fragment getItem(int position) {
|
public Fragment getItem(int position) {
|
||||||
Log.d(TAG, "Adapter getItem " + position);
|
Log.d(TAG, "Adapter getItem " + position);
|
||||||
final Bundle args = new Bundle();
|
final Bundle args = new Bundle();
|
||||||
|
args.putBoolean(SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR, false);
|
||||||
args.putInt(WifiCallingSettingsForSub.FRAGMENT_BUNDLE_SUBID,
|
args.putInt(WifiCallingSettingsForSub.FRAGMENT_BUNDLE_SUBID,
|
||||||
mSil.get(position).getSubscriptionId());
|
mSil.get(position).getSubscriptionId());
|
||||||
WifiCallingSettingsForSub fragment = new WifiCallingSettingsForSub();
|
WifiCallingSettingsForSub fragment = new WifiCallingSettingsForSub();
|
||||||
@@ -132,26 +145,6 @@ public class WifiCallingSettings extends SettingsPreferenceFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getWfcModeSummary(Context context, int wfcMode) {
|
|
||||||
int resId = com.android.internal.R.string.wifi_calling_off_summary;
|
|
||||||
if (ImsManager.isWfcEnabledByUser(context)) {
|
|
||||||
switch (wfcMode) {
|
|
||||||
case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
|
|
||||||
resId = com.android.internal.R.string.wfc_mode_wifi_only_summary;
|
|
||||||
break;
|
|
||||||
case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED:
|
|
||||||
resId = com.android.internal.R.string.wfc_mode_cellular_preferred_summary;
|
|
||||||
break;
|
|
||||||
case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED:
|
|
||||||
resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.e(TAG, "Unexpected WFC mode value: " + wfcMode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateSubList() {
|
private void updateSubList() {
|
||||||
mSil = SubscriptionManager.from(getActivity()).getActiveSubscriptionInfoList();
|
mSil = SubscriptionManager.from(getActivity()).getActiveSubscriptionInfoList();
|
||||||
|
|
||||||
@@ -159,7 +152,7 @@ public class WifiCallingSettings extends SettingsPreferenceFragment {
|
|||||||
if (mSil == null) {
|
if (mSil == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < mSil.size();) {
|
for (int i = 0; i < mSil.size(); ) {
|
||||||
ImsManager imsManager = ImsManager.getInstance(getActivity(),
|
ImsManager imsManager = ImsManager.getInstance(getActivity(),
|
||||||
mSil.get(i).getSimSlotIndex());
|
mSil.get(i).getSimSlotIndex());
|
||||||
if (!imsManager.isWfcEnabledByPlatform()) {
|
if (!imsManager.isWfcEnabledByPlatform()) {
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings;
|
package com.android.settings.wifi.calling;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
@@ -45,6 +45,10 @@ import com.android.ims.ImsConfig;
|
|||||||
import com.android.ims.ImsManager;
|
import com.android.ims.ImsManager;
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.internal.telephony.Phone;
|
import com.android.internal.telephony.Phone;
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.SettingsActivity;
|
||||||
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
|
import com.android.settings.Utils;
|
||||||
import com.android.settings.widget.SwitchBar;
|
import com.android.settings.widget.SwitchBar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,7 +58,7 @@ import com.android.settings.widget.SwitchBar;
|
|||||||
public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
||||||
implements SwitchBar.OnSwitchChangeListener,
|
implements SwitchBar.OnSwitchChangeListener,
|
||||||
Preference.OnPreferenceChangeListener {
|
Preference.OnPreferenceChangeListener {
|
||||||
private static final String TAG = "WifiCallingSettingsForSub";
|
private static final String TAG = "WifiCallingForSub";
|
||||||
|
|
||||||
//String keys for preference lookup
|
//String keys for preference lookup
|
||||||
private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
|
private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
|
||||||
@@ -130,12 +134,6 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getHelpResource() {
|
|
||||||
// Helper resource is already defined in the container fragment.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final OnPreferenceClickListener mUpdateAddressListener =
|
private final OnPreferenceClickListener mUpdateAddressListener =
|
||||||
new OnPreferenceClickListener() {
|
new OnPreferenceClickListener() {
|
||||||
/*
|
/*
|
||||||
@@ -226,8 +224,7 @@ public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
|||||||
|
|
||||||
// SubId should always be specified when creating this fragment. Either through
|
// SubId should always be specified when creating this fragment. Either through
|
||||||
// fragment.setArguments() or through savedInstanceState.
|
// fragment.setArguments() or through savedInstanceState.
|
||||||
if (getArguments() != null && getArguments().containsKey(FRAGMENT_BUNDLE_SUBID))
|
if (getArguments() != null && getArguments().containsKey(FRAGMENT_BUNDLE_SUBID)) {
|
||||||
{
|
|
||||||
mSubId = getArguments().getInt(FRAGMENT_BUNDLE_SUBID);
|
mSubId = getArguments().getInt(FRAGMENT_BUNDLE_SUBID);
|
||||||
} else if (savedInstanceState != null) {
|
} else if (savedInstanceState != null) {
|
||||||
mSubId = savedInstanceState.getInt(
|
mSubId = savedInstanceState.getInt(
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings.wifi;
|
package com.android.settings.wifi.calling;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
@@ -60,8 +60,7 @@ com.android.settings.applications.appinfo.PictureInPictureSettings
|
|||||||
com.android.settings.applications.appinfo.PictureInPictureDetails
|
com.android.settings.applications.appinfo.PictureInPictureDetails
|
||||||
com.android.settings.ApnSettings
|
com.android.settings.ApnSettings
|
||||||
com.android.settings.PrivacySettings
|
com.android.settings.PrivacySettings
|
||||||
com.android.settings.WifiCallingSettings
|
com.android.settings.wifi.calling.WifiCallingSettingsForSub
|
||||||
com.android.settings.WifiCallingSettingsForSub
|
|
||||||
com.android.settings.password.SetupChooseLockGeneric$SetupChooseLockGenericFragment
|
com.android.settings.password.SetupChooseLockGeneric$SetupChooseLockGenericFragment
|
||||||
com.android.settings.SetupRedactionInterstitial$SetupRedactionInterstitialFragment
|
com.android.settings.SetupRedactionInterstitial$SetupRedactionInterstitialFragment
|
||||||
com.android.settings.security.trustagent.TrustAgentSettings
|
com.android.settings.security.trustagent.TrustAgentSettings
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
com.android.settings.testutils.FakeToggleController
|
||||||
@@ -37,7 +37,9 @@ import com.android.settings.TestConfig;
|
|||||||
import com.android.settings.applications.ProcStatsData;
|
import com.android.settings.applications.ProcStatsData;
|
||||||
import com.android.settings.applications.ProcessStatsDetail;
|
import com.android.settings.applications.ProcessStatsDetail;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -48,7 +50,9 @@ import org.robolectric.annotation.Config;
|
|||||||
import org.robolectric.util.ReflectionHelpers;
|
import org.robolectric.util.ReflectionHelpers;
|
||||||
|
|
||||||
@RunWith(SettingsRobolectricTestRunner.class)
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, shadows = {
|
||||||
|
ShadowUserManager.class
|
||||||
|
})
|
||||||
public class AppMemoryPreferenceControllerTest {
|
public class AppMemoryPreferenceControllerTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
@@ -67,6 +71,7 @@ public class AppMemoryPreferenceControllerTest {
|
|||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
mContext = RuntimeEnvironment.application;
|
mContext = RuntimeEnvironment.application;
|
||||||
|
ShadowUserManager.getShadow().setIsAdminUser(true);
|
||||||
mController =
|
mController =
|
||||||
spy(new AppMemoryPreferenceController(mContext, mFragment, null /* lifecycle */));
|
spy(new AppMemoryPreferenceController(mContext, mFragment, null /* lifecycle */));
|
||||||
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
|
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
|
||||||
@@ -75,6 +80,11 @@ public class AppMemoryPreferenceControllerTest {
|
|||||||
when(mFragment.getActivity()).thenReturn(mActivity);
|
when(mFragment.getActivity()).thenReturn(mActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
ShadowUserManager.getShadow().reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getAvailabilityStatus_developmentSettingsEnabled_shouldReturnAvailable() {
|
public void getAvailabilityStatus_developmentSettingsEnabled_shouldReturnAvailable() {
|
||||||
Settings.Global.putInt(mContext.getContentResolver(),
|
Settings.Global.putInt(mContext.getContentResolver(),
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public class BluetoothDetailsHeaderControllerTest extends BluetoothDetailsContro
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testContextMock() {
|
public void testContextMock() {
|
||||||
assertThat(mContext.getString(R.string.bluetooth_connected)).isEqualTo("Connected");
|
assertThat(mContext.getString(R.string.bluetooth_connected)).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.datausage;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.NetworkTemplate;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settingslib.NetworkPolicyEditor;
|
||||||
|
import com.android.settingslib.net.DataUsageController;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
|
public class DataUsageSummaryPreferenceControllerTest {
|
||||||
|
private static final long UPDATE_BACKOFF_MS = TimeUnit.MINUTES.toMillis(13);
|
||||||
|
private static final long CYCLE_BACKOFF_MS = TimeUnit.DAYS.toMillis(6);
|
||||||
|
private static final long CYCLE_LENGTH_MS = TimeUnit.DAYS.toMillis(30);
|
||||||
|
private static final long USAGE1 = 373000000L;
|
||||||
|
private static final long LIMIT1 = 1000000000L;
|
||||||
|
private static final String CARRIER_NAME = "z-mobile";
|
||||||
|
private static final String PERIOD = "Feb";
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DataUsageController mDataUsageController;
|
||||||
|
@Mock
|
||||||
|
private DataUsageInfoController mDataInfoController;
|
||||||
|
@Mock
|
||||||
|
private DataUsageSummaryPreference mSummaryPreference;
|
||||||
|
@Mock
|
||||||
|
private NetworkPolicyEditor mPolicyEditor;
|
||||||
|
@Mock
|
||||||
|
private NetworkTemplate mNetworkTemplate;
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private DataUsageSummaryPreferenceController mController;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mContext = RuntimeEnvironment.application;
|
||||||
|
|
||||||
|
mController = new DataUsageSummaryPreferenceController(
|
||||||
|
mContext,
|
||||||
|
mDataUsageController,
|
||||||
|
mDataInfoController,
|
||||||
|
mNetworkTemplate,
|
||||||
|
mPolicyEditor,
|
||||||
|
R.string.cell_data_template,
|
||||||
|
true,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSummaryUpdate_onePlan_basic() {
|
||||||
|
final long now = System.currentTimeMillis();
|
||||||
|
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
|
||||||
|
|
||||||
|
final Intent intent = new Intent();
|
||||||
|
|
||||||
|
when(mDataUsageController.getDataUsageInfo()).thenReturn(info);
|
||||||
|
mController.setPlanValues(1 /* dataPlanCount */, LIMIT1, USAGE1);
|
||||||
|
mController.setCarrierValues(CARRIER_NAME, now - UPDATE_BACKOFF_MS, info.cycleEnd, intent);
|
||||||
|
|
||||||
|
mController.updateState(mSummaryPreference);
|
||||||
|
verify(mSummaryPreference).setLimitInfo(null);
|
||||||
|
verify(mSummaryPreference).setUsageInfo(info.cycleEnd, now - UPDATE_BACKOFF_MS,
|
||||||
|
CARRIER_NAME, 1 /* numPlans */, intent);
|
||||||
|
verify(mSummaryPreference).setChartEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSummaryUpdate_noPlan_basic() {
|
||||||
|
final long now = System.currentTimeMillis();
|
||||||
|
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
|
||||||
|
|
||||||
|
final Intent intent = new Intent();
|
||||||
|
|
||||||
|
when(mDataUsageController.getDataUsageInfo(any())).thenReturn(info);
|
||||||
|
mController.setPlanValues(0 /* dataPlanCount */, LIMIT1, USAGE1);
|
||||||
|
mController.setCarrierValues(CARRIER_NAME, now - UPDATE_BACKOFF_MS, info.cycleEnd, intent);
|
||||||
|
|
||||||
|
mController.updateState(mSummaryPreference);
|
||||||
|
verify(mSummaryPreference).setLimitInfo("500 MB Data warning / 1.00 GB Data limit");
|
||||||
|
verify(mSummaryPreference).setUsageInfo(info.cycleEnd, now - UPDATE_BACKOFF_MS,
|
||||||
|
CARRIER_NAME, 0 /* numPlans */, intent);
|
||||||
|
verify(mSummaryPreference).setChartEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSummaryUpdate_noCarrier_basic() {
|
||||||
|
final long now = System.currentTimeMillis();
|
||||||
|
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
|
||||||
|
|
||||||
|
when(mDataUsageController.getDataUsageInfo(any())).thenReturn(info);
|
||||||
|
mController.setPlanValues(0 /* dataPlanCount */, LIMIT1, USAGE1);
|
||||||
|
mController.setCarrierValues(null /* carrierName */, -1L /* snapshotTime */,
|
||||||
|
info.cycleEnd, null /* intent */);
|
||||||
|
mController.updateState(mSummaryPreference);
|
||||||
|
|
||||||
|
verify(mSummaryPreference).setLimitInfo("500 MB Data warning / 1.00 GB Data limit");
|
||||||
|
verify(mSummaryPreference).setUsageInfo(
|
||||||
|
info.cycleEnd,
|
||||||
|
-1L /* snapshotTime */,
|
||||||
|
null /* carrierName */,
|
||||||
|
0 /* numPlans */,
|
||||||
|
null /* launchIntent */);
|
||||||
|
verify(mSummaryPreference).setChartEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSummaryUpdate_noPlanData_basic() {
|
||||||
|
final long now = System.currentTimeMillis();
|
||||||
|
|
||||||
|
final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
|
||||||
|
|
||||||
|
when(mDataUsageController.getDataUsageInfo(any())).thenReturn(info);
|
||||||
|
mController.setPlanValues(0 /* dataPlanCount */, -1L /* dataPlanSize */, USAGE1);
|
||||||
|
mController.setCarrierValues(null /* carrierName */, -1L /* snapshotTime */,
|
||||||
|
info.cycleEnd, null /* intent */);
|
||||||
|
mController.updateState(mSummaryPreference);
|
||||||
|
|
||||||
|
verify(mSummaryPreference).setLimitInfo("500 MB Data warning / 1.00 GB Data limit");
|
||||||
|
verify(mSummaryPreference).setUsageInfo(
|
||||||
|
info.cycleEnd,
|
||||||
|
-1L /* snapshotTime */,
|
||||||
|
null /* carrierName */,
|
||||||
|
0 /* numPlans */,
|
||||||
|
null /* launchIntent */);
|
||||||
|
verify(mSummaryPreference).setChartEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataUsageController.DataUsageInfo createTestDataUsageInfo(long now) {
|
||||||
|
DataUsageController.DataUsageInfo info = new DataUsageController.DataUsageInfo();
|
||||||
|
info.carrier = CARRIER_NAME;
|
||||||
|
info.period = PERIOD;
|
||||||
|
info.startDate = now;
|
||||||
|
info.limitLevel = LIMIT1;
|
||||||
|
info.warningLevel = LIMIT1 >> 1;
|
||||||
|
info.usageLevel = USAGE1;
|
||||||
|
info.cycleStart = now - CYCLE_BACKOFF_MS;
|
||||||
|
info.cycleEnd = info.cycleStart + CYCLE_LENGTH_MS;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.datausage;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.support.v7.preference.PreferenceViewHolder;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
|
||||||
|
import com.android.settingslib.utils.StringUtil;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, shadows =
|
||||||
|
SettingsShadowResourcesImpl.class)
|
||||||
|
public class DataUsageSummaryPreferenceTest {
|
||||||
|
private static final long CYCLE_DURATION_MILLIS = 1000000000L;
|
||||||
|
private static final long UPDATE_LAG_MILLIS = 10000000L;
|
||||||
|
private static final String DUMMY_CARRIER = "z-mobile";
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private PreferenceViewHolder mHolder;
|
||||||
|
private DataUsageSummaryPreference mSummaryPreference;
|
||||||
|
private TextView mUsageTitle;
|
||||||
|
private TextView mCycleTime;
|
||||||
|
private TextView mCarrierInfo;
|
||||||
|
private TextView mDataLimits;
|
||||||
|
private Button mLaunchButton;
|
||||||
|
|
||||||
|
private long mCycleEnd;
|
||||||
|
private long mUpdateTime;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mContext = spy(RuntimeEnvironment.application);
|
||||||
|
mSummaryPreference = new DataUsageSummaryPreference(mContext, null /* attrs */);
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||||
|
View view = inflater.inflate(mSummaryPreference.getLayoutResource(), null /* root */,
|
||||||
|
false /* attachToRoot */);
|
||||||
|
|
||||||
|
mHolder = PreferenceViewHolder.createInstanceForTests(view);
|
||||||
|
|
||||||
|
final long now = System.currentTimeMillis();
|
||||||
|
mCycleEnd = now + CYCLE_DURATION_MILLIS;
|
||||||
|
mUpdateTime = now - UPDATE_LAG_MILLIS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetUsageInfo_withLaunchIntent_launchButtonShown() {
|
||||||
|
mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, DUMMY_CARRIER, 0 /* numPlans */,
|
||||||
|
new Intent());
|
||||||
|
|
||||||
|
bindViewHolder();
|
||||||
|
assertThat(mLaunchButton.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetUsageInfo_withoutLaunchIntent_launchButtonNotShown() {
|
||||||
|
mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, DUMMY_CARRIER, 0 /* numPlans */,
|
||||||
|
null /* launchIntent */);
|
||||||
|
|
||||||
|
bindViewHolder();
|
||||||
|
assertThat(mLaunchButton.getVisibility()).isEqualTo(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetUsageInfo_withDataPlans_carrierInfoShown() {
|
||||||
|
mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, DUMMY_CARRIER, 1 /* numPlans */,
|
||||||
|
new Intent());
|
||||||
|
|
||||||
|
bindViewHolder();
|
||||||
|
assertThat(mCarrierInfo.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetUsageInfo_withNoDataPlans_carrierInfoNotShown() {
|
||||||
|
mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, DUMMY_CARRIER, 0 /* numPlans */,
|
||||||
|
new Intent());
|
||||||
|
|
||||||
|
bindViewHolder();
|
||||||
|
assertThat(mCarrierInfo.getVisibility()).isEqualTo(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetUsageInfo_withNoDataPlans_usageTitleNotShown() {
|
||||||
|
mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, DUMMY_CARRIER, 0 /* numPlans */,
|
||||||
|
new Intent());
|
||||||
|
|
||||||
|
bindViewHolder();
|
||||||
|
assertThat(mUsageTitle.getVisibility()).isEqualTo(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetUsageInfo_withMultipleDataPlans_usageTitleShown() {
|
||||||
|
mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, DUMMY_CARRIER, 2 /* numPlans */,
|
||||||
|
new Intent());
|
||||||
|
|
||||||
|
bindViewHolder();
|
||||||
|
assertThat(mUsageTitle.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetUsageInfo_cycleRemainingTimeShown() {
|
||||||
|
mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, DUMMY_CARRIER, 0 /* numPlans */,
|
||||||
|
new Intent());
|
||||||
|
String cyclePrefix = StringUtil.formatElapsedTime(mContext, CYCLE_DURATION_MILLIS,
|
||||||
|
false /* withSeconds */).toString();
|
||||||
|
String text = mContext.getString(R.string.cycle_left_time_text, cyclePrefix);
|
||||||
|
|
||||||
|
bindViewHolder();
|
||||||
|
assertThat(mCycleTime.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
assertThat(mCycleTime.getText()).isEqualTo(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetLimitInfo_withLimitInfo_dataLimitsShown() {
|
||||||
|
final String limitText = "test limit text";
|
||||||
|
mSummaryPreference.setLimitInfo(limitText);
|
||||||
|
|
||||||
|
bindViewHolder();
|
||||||
|
assertThat(mDataLimits.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
assertThat(mDataLimits.getText()).isEqualTo(limitText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetLimitInfo_withNullLimitInfo_dataLimitsNotShown() {
|
||||||
|
mSummaryPreference.setLimitInfo(null);
|
||||||
|
|
||||||
|
bindViewHolder();
|
||||||
|
assertThat(mDataLimits.getVisibility()).isEqualTo(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindViewHolder() {
|
||||||
|
mSummaryPreference.onBindViewHolder(mHolder);
|
||||||
|
mUsageTitle = (TextView) mHolder.findViewById(R.id.usage_title);
|
||||||
|
mCycleTime = (TextView) mHolder.findViewById(R.id.cycle_left_time);
|
||||||
|
mCarrierInfo = (TextView) mHolder.findViewById(R.id.carrier_and_update);
|
||||||
|
mDataLimits = (TextView) mHolder.findViewById(R.id.data_limits);
|
||||||
|
mLaunchButton = (Button) mHolder.findViewById(R.id.launch_mdp_app_button);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
package com.android.settings.development;
|
package com.android.settings.development;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
@@ -33,6 +32,7 @@ import com.android.settings.R;
|
|||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
import com.android.settings.testutils.shadow.SettingsShadowResources;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||||
import com.android.settings.widget.SwitchBar;
|
import com.android.settings.widget.SwitchBar;
|
||||||
import com.android.settings.widget.ToggleSwitch;
|
import com.android.settings.widget.ToggleSwitch;
|
||||||
import com.android.settingslib.development.AbstractEnableAdbPreferenceController;
|
import com.android.settingslib.development.AbstractEnableAdbPreferenceController;
|
||||||
@@ -52,7 +52,9 @@ import org.robolectric.util.ReflectionHelpers;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RunWith(SettingsRobolectricTestRunner.class)
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, shadows = {
|
||||||
|
ShadowUserManager.class
|
||||||
|
})
|
||||||
public class DevelopmentSettingsDashboardFragmentTest {
|
public class DevelopmentSettingsDashboardFragmentTest {
|
||||||
|
|
||||||
private SwitchBar mSwitchBar;
|
private SwitchBar mSwitchBar;
|
||||||
@@ -68,11 +70,13 @@ public class DevelopmentSettingsDashboardFragmentTest {
|
|||||||
mSwitch = mSwitchBar.getSwitch();
|
mSwitch = mSwitchBar.getSwitch();
|
||||||
mDashboard = spy(new DevelopmentSettingsDashboardFragment());
|
mDashboard = spy(new DevelopmentSettingsDashboardFragment());
|
||||||
ReflectionHelpers.setField(mDashboard, "mSwitchBar", mSwitchBar);
|
ReflectionHelpers.setField(mDashboard, "mSwitchBar", mSwitchBar);
|
||||||
|
ShadowUserManager.getShadow().setIsAdminUser(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
ShadowEnableDevelopmentSettingWarningDialog.reset();
|
ShadowEnableDevelopmentSettingWarningDialog.reset();
|
||||||
|
ShadowUserManager.getShadow().reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -101,7 +105,7 @@ public class DevelopmentSettingsDashboardFragmentTest {
|
|||||||
SettingsShadowResources.class,
|
SettingsShadowResources.class,
|
||||||
SettingsShadowResources.SettingsShadowTheme.class
|
SettingsShadowResources.SettingsShadowTheme.class
|
||||||
})
|
})
|
||||||
public void searchIndex_pageDisabled_shouldAddAllKeysToNonIndexable() {
|
public void searchIndex_pageDisabledBySetting_shouldAddAllKeysToNonIndexable() {
|
||||||
final Context appContext = RuntimeEnvironment.application;
|
final Context appContext = RuntimeEnvironment.application;
|
||||||
DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, false);
|
DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, false);
|
||||||
|
|
||||||
@@ -109,7 +113,24 @@ public class DevelopmentSettingsDashboardFragmentTest {
|
|||||||
DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
|
DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
|
||||||
.getNonIndexableKeys(appContext);
|
.getNonIndexableKeys(appContext);
|
||||||
|
|
||||||
assertThat(nonIndexableKeys).contains("development_prefs_screen");
|
assertThat(nonIndexableKeys).contains("enable_adb");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Config(shadows = {
|
||||||
|
SettingsShadowResources.class,
|
||||||
|
SettingsShadowResources.SettingsShadowTheme.class
|
||||||
|
})
|
||||||
|
public void searchIndex_pageDisabledForNonAdmin_shouldAddAllKeysToNonIndexable() {
|
||||||
|
final Context appContext = RuntimeEnvironment.application;
|
||||||
|
DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, true);
|
||||||
|
ShadowUserManager.getShadow().setIsAdminUser(false);
|
||||||
|
|
||||||
|
final List<String> nonIndexableKeys =
|
||||||
|
DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
|
||||||
|
.getNonIndexableKeys(appContext);
|
||||||
|
|
||||||
|
assertThat(nonIndexableKeys).contains("enable_adb");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import android.content.Context;
|
|||||||
|
|
||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||||
import com.android.settings.widget.SwitchBar;
|
import com.android.settings.widget.SwitchBar;
|
||||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||||
@@ -47,7 +48,8 @@ import java.util.ArrayList;
|
|||||||
@RunWith(SettingsRobolectricTestRunner.class)
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
|
||||||
shadows = {
|
shadows = {
|
||||||
ShadowUtils.class
|
ShadowUtils.class,
|
||||||
|
ShadowUserManager.class
|
||||||
})
|
})
|
||||||
public class DevelopmentSwitchBarControllerTest {
|
public class DevelopmentSwitchBarControllerTest {
|
||||||
|
|
||||||
@@ -63,6 +65,7 @@ public class DevelopmentSwitchBarControllerTest {
|
|||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
mContext = RuntimeEnvironment.application;
|
mContext = RuntimeEnvironment.application;
|
||||||
|
ShadowUserManager.getShadow().setIsAdminUser(true);
|
||||||
mLifecycleOwner = () -> mLifecycle;
|
mLifecycleOwner = () -> mLifecycle;
|
||||||
mLifecycle = new Lifecycle(mLifecycleOwner);
|
mLifecycle = new Lifecycle(mLifecycleOwner);
|
||||||
mSwitchBar = new SwitchBar(mContext);
|
mSwitchBar = new SwitchBar(mContext);
|
||||||
@@ -72,6 +75,7 @@ public class DevelopmentSwitchBarControllerTest {
|
|||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
ShadowUtils.reset();
|
ShadowUtils.reset();
|
||||||
|
ShadowUserManager.getShadow().reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import com.android.settings.search.DatabaseIndexingManager;
|
|||||||
import com.android.settings.testutils.FakeFeatureFactory;
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||||
|
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||||
import com.android.settingslib.development.DevelopmentSettingsEnabler;
|
import com.android.settingslib.development.DevelopmentSettingsEnabler;
|
||||||
|
|
||||||
@@ -60,7 +61,8 @@ import org.robolectric.util.ReflectionHelpers;
|
|||||||
@RunWith(SettingsRobolectricTestRunner.class)
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
|
||||||
shadows = {
|
shadows = {
|
||||||
ShadowUtils.class
|
ShadowUtils.class,
|
||||||
|
ShadowUserManager.class,
|
||||||
})
|
})
|
||||||
public class BuildNumberPreferenceControllerTest {
|
public class BuildNumberPreferenceControllerTest {
|
||||||
|
|
||||||
@@ -84,6 +86,7 @@ public class BuildNumberPreferenceControllerTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
ShadowUserManager.getShadow().setIsAdminUser(true);
|
||||||
mFactory = FakeFeatureFactory.setupForTest();
|
mFactory = FakeFeatureFactory.setupForTest();
|
||||||
mLifecycleOwner = () -> mLifecycle;
|
mLifecycleOwner = () -> mLifecycle;
|
||||||
mLifecycle = new Lifecycle(mLifecycleOwner);
|
mLifecycle = new Lifecycle(mLifecycleOwner);
|
||||||
@@ -98,6 +101,7 @@ public class BuildNumberPreferenceControllerTest {
|
|||||||
@After
|
@After
|
||||||
public void tearDown() {
|
public void tearDown() {
|
||||||
ShadowUtils.reset();
|
ShadowUtils.reset();
|
||||||
|
ShadowUserManager.getShadow().reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -21,15 +21,18 @@ import static com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
|
|||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.doNothing;
|
import static org.mockito.Mockito.doNothing;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.preference.PreferenceScreen;
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.util.ArrayMap;
|
||||||
|
|
||||||
import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
|
import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
|
||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
@@ -39,6 +42,7 @@ import com.android.settings.testutils.shadow.SettingsShadowResources;
|
|||||||
import com.android.settings.testutils.shadow.SettingsShadowSystemProperties;
|
import com.android.settings.testutils.shadow.SettingsShadowSystemProperties;
|
||||||
import com.android.settings.testutils.shadow.ShadowConnectivityManager;
|
import com.android.settings.testutils.shadow.ShadowConnectivityManager;
|
||||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||||
|
import com.android.settingslib.core.AbstractPreferenceController;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -48,6 +52,11 @@ import org.mockito.MockitoAnnotations;
|
|||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
import org.robolectric.shadows.ShadowApplication;
|
import org.robolectric.shadows.ShadowApplication;
|
||||||
|
import org.robolectric.util.ReflectionHelpers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@RunWith(SettingsRobolectricTestRunner.class)
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
@Config(
|
@Config(
|
||||||
@@ -97,4 +106,23 @@ public class MyDeviceInfoFragmentTest {
|
|||||||
|
|
||||||
verify(mScreen).setInitialExpandedChildrenCount(Integer.MAX_VALUE);
|
verify(mScreen).setInitialExpandedChildrenCount(Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onActivityResult_shouldCallBuildNumberPreferenceController() {
|
||||||
|
final BuildNumberPreferenceController controller =
|
||||||
|
mock(BuildNumberPreferenceController.class);
|
||||||
|
final Map<Class, List<AbstractPreferenceController>> preferenceControllers =
|
||||||
|
new ArrayMap<>();
|
||||||
|
final List<AbstractPreferenceController> controllerList = new ArrayList<>();
|
||||||
|
controllerList.add(controller);
|
||||||
|
preferenceControllers.put(BuildNumberPreferenceController.class, controllerList);
|
||||||
|
ReflectionHelpers.setField(mSettings, "mPreferenceControllers", preferenceControllers);
|
||||||
|
|
||||||
|
final int requestCode = 1;
|
||||||
|
final int resultCode = 2;
|
||||||
|
final Intent data = new Intent();
|
||||||
|
mSettings.onActivityResult(requestCode, resultCode, data);
|
||||||
|
|
||||||
|
verify(controller).onActivityResult(requestCode, resultCode, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -220,4 +220,9 @@ public class BatteryAppListPreferenceControllerTest {
|
|||||||
|
|
||||||
assertThat(mPreferenceController.isAvailable()).isFalse();
|
assertThat(mPreferenceController.isAvailable()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNeverUseFakeData() {
|
||||||
|
assertThat(BatteryAppListPreferenceController.USE_FAKE_DATA).isFalse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.fuelgauge.batterysaver;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import android.arch.lifecycle.LifecycleOwner;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.widget.TwoStateButtonPreference;
|
||||||
|
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
import org.robolectric.Shadows;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.shadows.ShadowPowerManager;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
|
||||||
|
shadows = com.android.settings.testutils.shadow.ShadowPowerManager.class)
|
||||||
|
public class BatterySaverButtonPreferenceControllerTest {
|
||||||
|
private BatterySaverButtonPreferenceController mController;
|
||||||
|
private Context mContext;
|
||||||
|
private Lifecycle mLifecycle;
|
||||||
|
private LifecycleOwner mLifecycleOwner;
|
||||||
|
private Button mButtonOn;
|
||||||
|
private Button mButtonOff;
|
||||||
|
private ShadowPowerManager mShadowPowerManager;
|
||||||
|
@Mock
|
||||||
|
private TwoStateButtonPreference mPreference;
|
||||||
|
@Mock
|
||||||
|
private PreferenceScreen mPreferenceScreen;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
|
mLifecycleOwner = () -> mLifecycle;
|
||||||
|
mLifecycle = new Lifecycle(mLifecycleOwner);
|
||||||
|
mContext = spy(RuntimeEnvironment.application);
|
||||||
|
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
||||||
|
mShadowPowerManager = Shadows.shadowOf(powerManager);
|
||||||
|
doReturn(mPreference).when(mPreferenceScreen).findPreference(anyString());
|
||||||
|
|
||||||
|
mButtonOn = new Button(mContext);
|
||||||
|
mButtonOn.setId(R.id.state_on_button);
|
||||||
|
doReturn(mButtonOn).when(mPreference).getStateOnButton();
|
||||||
|
mButtonOff = new Button(mContext);
|
||||||
|
mButtonOff.setId(R.id.state_off_button);
|
||||||
|
doReturn(mButtonOff).when(mPreference).getStateOffButton();
|
||||||
|
|
||||||
|
mController = new BatterySaverButtonPreferenceController(mContext, mLifecycle);
|
||||||
|
mController.displayPreference(mPreferenceScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateState_lowPowerOn_displayButtonOff() {
|
||||||
|
mShadowPowerManager.setIsPowerSaveMode(true);
|
||||||
|
|
||||||
|
mController.updateState(mPreference);
|
||||||
|
|
||||||
|
assertThat(mButtonOn.getVisibility()).isEqualTo(View.GONE);
|
||||||
|
assertThat(mButtonOff.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateState_lowPowerOff_displayButtonOn() {
|
||||||
|
mShadowPowerManager.setIsPowerSaveMode(false);
|
||||||
|
|
||||||
|
mController.updateState(mPreference);
|
||||||
|
|
||||||
|
assertThat(mButtonOn.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
assertThat(mButtonOff.getVisibility()).isEqualTo(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnClick_clickButtonOn_setPowerSaveMode() {
|
||||||
|
mController.onClick(mButtonOn);
|
||||||
|
|
||||||
|
assertThat(mShadowPowerManager.isPowerSaveMode()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnClick_clickButtonOff_clearPowerSaveMode() {
|
||||||
|
mController.onClick(mButtonOff);
|
||||||
|
|
||||||
|
assertThat(mShadowPowerManager.isPowerSaveMode()).isFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -137,7 +137,6 @@ public class BaseSearchIndexProviderTest {
|
|||||||
final List<String> nonIndexableKeys = provider
|
final List<String> nonIndexableKeys = provider
|
||||||
.getNonIndexableKeys(RuntimeEnvironment.application);
|
.getNonIndexableKeys(RuntimeEnvironment.application);
|
||||||
|
|
||||||
assertThat(nonIndexableKeys).containsAllOf("status_header", "limit_summary",
|
assertThat(nonIndexableKeys).contains("status_header");
|
||||||
"restrict_background");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.settings.search.actionbar;
|
|||||||
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -27,6 +28,7 @@ import android.view.MenuItem;
|
|||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settingslib.core.lifecycle.ObservableFragment;
|
||||||
import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment;
|
import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -42,26 +44,47 @@ public class SearchMenuControllerTest {
|
|||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private Menu mMenu;
|
private Menu mMenu;
|
||||||
private TestFragment mHost;
|
private TestPreferenceFragment mPreferenceHost;
|
||||||
|
private ObservableFragment mHost;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
mHost = new TestFragment();
|
mHost = new ObservableFragment();
|
||||||
|
mPreferenceHost = new TestPreferenceFragment();
|
||||||
|
|
||||||
|
when(mMenu.add(Menu.NONE, Menu.NONE, 0 /* order */, R.string.search_menu))
|
||||||
|
.thenReturn(mock(MenuItem.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void init_shouldAddMenu() {
|
public void init_prefFragment_shouldAddMenu() {
|
||||||
when(mMenu.add(Menu.NONE, Menu.NONE, 0 /* order */, R.string.search_menu))
|
SearchMenuController.init(mPreferenceHost);
|
||||||
.thenReturn(mock(MenuItem.class));
|
mPreferenceHost.getLifecycle().onCreateOptionsMenu(mMenu, null /* inflater */);
|
||||||
|
|
||||||
|
verify(mMenu).add(Menu.NONE, Menu.NONE, 0 /* order */, R.string.search_menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void init_observableFragment_shouldAddMenu() {
|
||||||
SearchMenuController.init(mHost);
|
SearchMenuController.init(mHost);
|
||||||
mHost.getLifecycle().onCreateOptionsMenu(mMenu, null /* inflater */);
|
mHost.getLifecycle().onCreateOptionsMenu(mMenu, null /* inflater */);
|
||||||
|
|
||||||
verify(mMenu).add(Menu.NONE, Menu.NONE, 0 /* order */, R.string.search_menu);
|
verify(mMenu).add(Menu.NONE, Menu.NONE, 0 /* order */, R.string.search_menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TestFragment extends ObservablePreferenceFragment {
|
@Test
|
||||||
|
public void init_doNotNeedSearchIcon_shouldNotAddMenu() {
|
||||||
|
final Bundle args = new Bundle();
|
||||||
|
args.putBoolean(SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR, false);
|
||||||
|
mHost.setArguments(args);
|
||||||
|
|
||||||
|
SearchMenuController.init(mHost);
|
||||||
|
mHost.getLifecycle().onCreateOptionsMenu(mMenu, null /* inflater */);
|
||||||
|
verifyZeroInteractions(mMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TestPreferenceFragment extends ObservablePreferenceFragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import android.net.Uri;
|
|||||||
|
|
||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
import com.android.settings.testutils.DatabaseTestUtils;
|
import com.android.settings.testutils.DatabaseTestUtils;
|
||||||
|
import com.android.settings.testutils.FakeToggleController;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import com.android.settings.search.FakeIndexProvider;
|
|||||||
import com.android.settings.search.SearchFeatureProvider;
|
import com.android.settings.search.SearchFeatureProvider;
|
||||||
import com.android.settings.search.SearchFeatureProviderImpl;
|
import com.android.settings.search.SearchFeatureProviderImpl;
|
||||||
import com.android.settings.testutils.FakeFeatureFactory;
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
|
import com.android.settings.testutils.FakeToggleController;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import android.net.Uri;
|
|||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.TestConfig;
|
import com.android.settings.TestConfig;
|
||||||
import com.android.settings.core.BasePreferenceController;
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
import com.android.settings.testutils.FakeToggleController;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.slices;
|
||||||
|
|
||||||
|
import static com.android.settings.TestConfig.SDK_VERSION;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.XmlResourceParser;
|
||||||
|
import android.provider.SearchIndexableResource;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Xml;
|
||||||
|
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.core.TogglePreferenceController;
|
||||||
|
import com.android.settings.core.codeinspection.ClassScanner;
|
||||||
|
import com.android.settings.core.codeinspection.CodeInspector;
|
||||||
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
|
import com.android.settings.search.DatabaseIndexingUtils;
|
||||||
|
import com.android.settings.search.Indexable;
|
||||||
|
import com.android.settings.search.SearchFeatureProvider;
|
||||||
|
import com.android.settings.search.SearchFeatureProviderImpl;
|
||||||
|
import com.android.settings.search.XmlParserUtils;
|
||||||
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = SDK_VERSION)
|
||||||
|
public class SliceControllerInXmlTest {
|
||||||
|
|
||||||
|
private static final List<Class> mSliceControllerClasses = new ArrayList<>(Arrays.asList(
|
||||||
|
TogglePreferenceController.class
|
||||||
|
));
|
||||||
|
|
||||||
|
private final List<String> mXmlDeclaredControllers = new ArrayList<>();
|
||||||
|
private final List<String> mGrandfatheredClasses = new ArrayList<>();
|
||||||
|
|
||||||
|
private final String ERROR_MISSING_CONTROLLER =
|
||||||
|
"The following controllers were expected to be declared by "
|
||||||
|
+ "'settings:controller=Controller_Class_Name' in their corresponding Xml. "
|
||||||
|
+ "If it should not appear in XML, add the controller's classname to "
|
||||||
|
+ "grandfather_slice_controller_not_in_xml. Controllers:\n";
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
SearchFeatureProvider mSearchProvider;
|
||||||
|
private FakeFeatureFactory mFakeFeatureFactory;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mContext = spy(RuntimeEnvironment.application);
|
||||||
|
|
||||||
|
mSearchProvider = new SearchFeatureProviderImpl();
|
||||||
|
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||||
|
mFakeFeatureFactory.searchFeatureProvider = mSearchProvider;
|
||||||
|
|
||||||
|
CodeInspector.initializeGrandfatherList(mGrandfatheredClasses,
|
||||||
|
"grandfather_slice_controller_not_in_xml");
|
||||||
|
initDeclaredControllers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initDeclaredControllers() {
|
||||||
|
final List<Integer> xmlResources = getIndexableXml();
|
||||||
|
XmlResourceParser parser;
|
||||||
|
|
||||||
|
for (int xmlResId : xmlResources) {
|
||||||
|
try {
|
||||||
|
parser = mContext.getResources().getXml(xmlResId);
|
||||||
|
|
||||||
|
int type;
|
||||||
|
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||||
|
&& type != XmlPullParser.START_TAG) {
|
||||||
|
// Parse next until start tag is found
|
||||||
|
}
|
||||||
|
|
||||||
|
final int outerDepth = parser.getDepth();
|
||||||
|
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||||
|
String controllerClassName;
|
||||||
|
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||||
|
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||||
|
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
controllerClassName = XmlParserUtils.getController(mContext, attrs);
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(controllerClassName)) {
|
||||||
|
mXmlDeclaredControllers.add(controllerClassName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Assume an issue with robolectric resources
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllControllersDeclaredInXml() throws Exception {
|
||||||
|
final List<Class<?>> classes = new ClassScanner().getClassesForPackage(
|
||||||
|
mContext.getPackageName());
|
||||||
|
final List<String> missingControllersInXml = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Class<?> clazz : classes) {
|
||||||
|
if (!isInlineSliceClass(clazz)) {
|
||||||
|
// Only care about inline-slice controller classes.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mXmlDeclaredControllers.contains(clazz.getName())) {
|
||||||
|
// Class clazz should have been declared in XML (unless whitelisted).
|
||||||
|
missingControllersInXml.add(clazz.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removed whitelisted classes
|
||||||
|
missingControllersInXml.removeAll(mGrandfatheredClasses);
|
||||||
|
|
||||||
|
final String missingControllerError = buildErrorMessage(ERROR_MISSING_CONTROLLER,
|
||||||
|
missingControllersInXml);
|
||||||
|
|
||||||
|
assertWithMessage(missingControllerError).that(missingControllersInXml).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInlineSliceClass(Class clazz) {
|
||||||
|
while (clazz != null) {
|
||||||
|
clazz = clazz.getSuperclass();
|
||||||
|
if (mSliceControllerClasses.contains(clazz)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildErrorMessage(String errorSummary, List<String> errorClasses) {
|
||||||
|
final StringBuilder error = new StringBuilder(errorSummary);
|
||||||
|
for (String c : errorClasses) {
|
||||||
|
error.append(c).append("\n");
|
||||||
|
}
|
||||||
|
return error.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> getIndexableXml() {
|
||||||
|
final List<Integer> xmlResSet = new ArrayList<>();
|
||||||
|
|
||||||
|
final Collection<Class> indexableClasses = FeatureFactory.getFactory(
|
||||||
|
mContext).getSearchFeatureProvider().getSearchIndexableResources()
|
||||||
|
.getProviderValues();
|
||||||
|
|
||||||
|
for (Class clazz : indexableClasses) {
|
||||||
|
|
||||||
|
Indexable.SearchIndexProvider provider = DatabaseIndexingUtils.getSearchIndexProvider(
|
||||||
|
clazz);
|
||||||
|
|
||||||
|
if (provider == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SearchIndexableResource> resources = provider.getXmlResourcesToIndex(mContext,
|
||||||
|
true);
|
||||||
|
|
||||||
|
if (resources == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (SearchIndexableResource resource : resources) {
|
||||||
|
// Add '0's anyway. It won't break the test.
|
||||||
|
xmlResSet.add(resource.xmlResId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return xmlResSet;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -68,7 +68,7 @@ public class SettingsSuggestionsTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void wifiCallingSuggestion_isValid() {
|
public void wifiCallingSuggestion_isValid() {
|
||||||
assertSuggestionEquals("com.android.settings.wifi.WifiCallingSuggestionActivity",
|
assertSuggestionEquals("com.android.settings.wifi.calling.WifiCallingSuggestionActivity",
|
||||||
CATEGORY_FIRST_IMPRESSION,
|
CATEGORY_FIRST_IMPRESSION,
|
||||||
R.string.wifi_calling_suggestion_title, R.string.wifi_calling_suggestion_summary);
|
R.string.wifi_calling_suggestion_title, R.string.wifi_calling_suggestion_summary);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings.slices;
|
package com.android.settings.testutils;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.testutils.shadow;
|
||||||
|
|
||||||
|
import android.os.PowerManager;
|
||||||
|
|
||||||
|
import org.robolectric.annotation.Implementation;
|
||||||
|
import org.robolectric.annotation.Implements;
|
||||||
|
|
||||||
|
@Implements(PowerManager.class)
|
||||||
|
public class ShadowPowerManager extends org.robolectric.shadows.ShadowPowerManager {
|
||||||
|
@Implementation
|
||||||
|
public boolean setPowerSaveMode(boolean mode) {
|
||||||
|
setIsPowerSaveMode(mode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -105,6 +105,24 @@ public class MasterCheckBoxPreferenceTest {
|
|||||||
assertThat(checkBox.isEnabled()).isTrue();
|
assertThat(checkBox.isEnabled()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onBindViewHolder_shouldSetCheckboxEnabledState() {
|
||||||
|
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||||
|
LayoutInflater.from(mContext).inflate(
|
||||||
|
R.layout.preference_widget_master_checkbox, null));
|
||||||
|
final CheckBox checkBox = (CheckBox) holder.findViewById(R.id.checkboxWidget);
|
||||||
|
|
||||||
|
mPreference.setCheckBoxEnabled(false);
|
||||||
|
mPreference.onBindViewHolder(holder);
|
||||||
|
|
||||||
|
assertThat(mPreference.isEnabled()).isTrue();
|
||||||
|
assertThat(checkBox.isEnabled()).isFalse();
|
||||||
|
|
||||||
|
mPreference.setCheckBoxEnabled(true);
|
||||||
|
assertThat(mPreference.isEnabled()).isTrue();
|
||||||
|
assertThat(checkBox.isEnabled()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void clickWidgetView_shouldToggleCheckBox() {
|
public void clickWidgetView_shouldToggleCheckBox() {
|
||||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.widget;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
|
public class TwoStateButtonPreferenceControllerTest {
|
||||||
|
private static final String KEY = "pref_key";
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PreferenceScreen mPreferenceScreen;
|
||||||
|
@Mock
|
||||||
|
private TwoStateButtonPreference mPreference;
|
||||||
|
private TwoStateButtonPreferenceController mController;
|
||||||
|
private Context mContext;
|
||||||
|
private Button mButtonOn;
|
||||||
|
private Button mButtonOff;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mContext = spy(RuntimeEnvironment.application);
|
||||||
|
doReturn(mPreference).when(mPreferenceScreen).findPreference(anyString());
|
||||||
|
mButtonOn = new Button(mContext);
|
||||||
|
doReturn(mButtonOn).when(mPreference).getStateOnButton();
|
||||||
|
mButtonOff = new Button(mContext);
|
||||||
|
doReturn(mButtonOff).when(mPreference).getStateOffButton();
|
||||||
|
|
||||||
|
mController = new TestButtonsPreferenceController(mContext, KEY);
|
||||||
|
mController.displayPreference(mPreferenceScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetButtonVisibility_stateOn_onlyShowButtonOn() {
|
||||||
|
mController.setButtonVisibility(true /* stateOn */);
|
||||||
|
|
||||||
|
assertThat(mButtonOn.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
assertThat(mButtonOff.getVisibility()).isEqualTo(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetButtonVisibility_stateOff_onlyShowButtonOff() {
|
||||||
|
mController.setButtonVisibility(false /* stateOn */);
|
||||||
|
|
||||||
|
assertThat(mButtonOn.getVisibility()).isEqualTo(View.GONE);
|
||||||
|
assertThat(mButtonOff.getVisibility()).isEqualTo(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetButtonEnabled_enabled_buttonEnabled() {
|
||||||
|
mController.setButtonEnabled(true /* enabled */);
|
||||||
|
|
||||||
|
assertThat(mButtonOn.isEnabled()).isTrue();
|
||||||
|
assertThat(mButtonOff.isEnabled()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetButtonEnabled_disabled_buttonDisabled() {
|
||||||
|
mController.setButtonEnabled(false /* enabled */);
|
||||||
|
|
||||||
|
assertThat(mButtonOn.isEnabled()).isFalse();
|
||||||
|
assertThat(mButtonOff.isEnabled()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller to test methods in {@link TwoStateButtonPreferenceController}
|
||||||
|
*/
|
||||||
|
public static class TestButtonsPreferenceController extends
|
||||||
|
TwoStateButtonPreferenceController {
|
||||||
|
|
||||||
|
TestButtonsPreferenceController(Context context, String key) {
|
||||||
|
super(context, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onButtonClicked(boolean stateOn) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAvailabilityStatus() {
|
||||||
|
return AVAILABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,6 +53,15 @@
|
|||||||
<meta-data android:name="com.android.settings.summary" android:resource="@string/manufacturer_settings_summary" />
|
<meta-data android:name="com.android.settings.summary" android:resource="@string/manufacturer_settings_summary" />
|
||||||
<meta-data android:name="com.android.settings.icon" android:resource="@drawable/ic_settings_applications" />
|
<meta-data android:name="com.android.settings.icon" android:resource="@drawable/ic_settings_applications" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<service android:name="com.android.settings.accounts.TestAuthService">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.accounts.AccountAuthenticator" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data android:name="android.accounts.AccountAuthenticator"
|
||||||
|
android:resource="@xml/authenticator" />
|
||||||
|
</service>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
|
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
|
||||||
|
|||||||
@@ -28,4 +28,7 @@
|
|||||||
<string name="manufacturer_hello" translatable="false">Hello Manufacturer!</string>
|
<string name="manufacturer_hello" translatable="false">Hello Manufacturer!</string>
|
||||||
<string name="manufacturer_settings_title" translatable="false">Manufacturer</string>
|
<string name="manufacturer_settings_title" translatable="false">Manufacturer</string>
|
||||||
<string name="manufacturer_settings_summary" translatable="false">Manufacturer hook that can be used to start activity of choice</string>
|
<string name="manufacturer_settings_summary" translatable="false">Manufacturer hook that can be used to start activity of choice</string>
|
||||||
|
<string name="account_auth_label" translatable="false">Settings Test Account</string>
|
||||||
|
<string name="account_type" translatable="false">com.settingstest.account-prefs</string>
|
||||||
|
<string name="account_pref_title" translatable="false">Test preference for external account</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
23
tests/unit/res/xml/account_preferences.xml
Normal file
23
tests/unit/res/xml/account_preferences.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2018 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:key="account_test_switch"
|
||||||
|
android:title="@string/account_pref_title" />
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
||||||
|
|
||||||
22
tests/unit/res/xml/authenticator.xml
Normal file
22
tests/unit/res/xml/authenticator.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2018 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<account-authenticator
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:label="@string/account_auth_label"
|
||||||
|
android:icon="@drawable/ic_settings_applications"
|
||||||
|
android:accountType="@string/account_type"
|
||||||
|
android:accountPreferences="@xml/account_preferences" />
|
||||||
|
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.settings.accounts;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.support.test.InstrumentationRegistry;
|
||||||
|
import android.support.test.filters.SmallTest;
|
||||||
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
|
import android.support.test.uiautomator.UiDevice;
|
||||||
|
import android.support.test.uiautomator.UiObject;
|
||||||
|
import android.support.test.uiautomator.UiSelector;
|
||||||
|
import android.support.test.uiautomator.UiScrollable;
|
||||||
|
import android.support.test.uiautomator.UiObjectNotFoundException;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@SmallTest
|
||||||
|
public class AccountsSettingsTest {
|
||||||
|
|
||||||
|
private static final String ACCOUNTS = "Accounts";
|
||||||
|
private static final String ACCOUNT_TYPE = "com.settingstest.account-prefs";
|
||||||
|
private static final String PREF_TITLE = "Test preference for external account";
|
||||||
|
|
||||||
|
private UiDevice mDevice;
|
||||||
|
private Context mContext;
|
||||||
|
private String mTargetPackage;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
|
||||||
|
mContext = InstrumentationRegistry.getTargetContext();
|
||||||
|
mTargetPackage = mContext.getPackageName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExternalAccountInfoExists() throws UiObjectNotFoundException {
|
||||||
|
// add a test account
|
||||||
|
final String testAccountName = "Test Account";
|
||||||
|
final Account account = new Account(testAccountName, ACCOUNT_TYPE);
|
||||||
|
final AccountManager accountManager = AccountManager.get(mContext);
|
||||||
|
final boolean accountAdded =
|
||||||
|
accountManager.addAccountExplicitly(account, null /* password */, null /* userdata */);
|
||||||
|
assertThat(accountAdded).isTrue();
|
||||||
|
|
||||||
|
// launch Accounts Settings and select the test account
|
||||||
|
launchAccountsSettings();
|
||||||
|
mDevice.findObject(new UiSelector().text(testAccountName)).click();
|
||||||
|
final UiObject testPreference = mDevice.findObject(new UiSelector().text(PREF_TITLE));
|
||||||
|
// remove test account
|
||||||
|
accountManager.removeAccountExplicitly(account);
|
||||||
|
|
||||||
|
assertThat(testPreference.exists()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void launchAccountsSettings() throws UiObjectNotFoundException {
|
||||||
|
// launch settings
|
||||||
|
Intent settingsIntent = new Intent(Intent.ACTION_MAIN)
|
||||||
|
.addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
.setPackage(mTargetPackage)
|
||||||
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
mContext.startActivity(settingsIntent);
|
||||||
|
// selects Accounts
|
||||||
|
final UiScrollable settings = new UiScrollable(
|
||||||
|
new UiSelector().packageName(mTargetPackage).scrollable(true));
|
||||||
|
final String titleAccounts = ACCOUNTS;
|
||||||
|
settings.scrollTextIntoView(titleAccounts);
|
||||||
|
mDevice.findObject(new UiSelector().text(titleAccounts)).click();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.settings.accounts;
|
||||||
|
|
||||||
|
import android.accounts.AbstractAccountAuthenticator;
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountAuthenticatorResponse;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.accounts.NetworkErrorException;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
public class Authenticator extends AbstractAccountAuthenticator {
|
||||||
|
|
||||||
|
public Authenticator(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle editProperties(AccountAuthenticatorResponse r, String s) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle addAccount(AccountAuthenticatorResponse r, String s, String s2, String[] strings,
|
||||||
|
Bundle bundle) throws NetworkErrorException {
|
||||||
|
final Bundle result = new Bundle();
|
||||||
|
result.putString(AccountManager.KEY_ACCOUNT_NAME, "Test Account");
|
||||||
|
result.putString(AccountManager.KEY_ACCOUNT_TYPE, s);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle confirmCredentials(AccountAuthenticatorResponse r, Account account, Bundle bundle)
|
||||||
|
throws NetworkErrorException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle getAuthToken(AccountAuthenticatorResponse r, Account account, String s,
|
||||||
|
Bundle bundle) throws NetworkErrorException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthTokenLabel(String s) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle updateCredentials(AccountAuthenticatorResponse r, Account account, String s,
|
||||||
|
Bundle bundle) throws NetworkErrorException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle hasFeatures(AccountAuthenticatorResponse r, Account account, String[] strings)
|
||||||
|
throws NetworkErrorException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.settings.accounts;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
public class TestAuthService extends Service {
|
||||||
|
|
||||||
|
private Authenticator mAuthenticator;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
mAuthenticator = new Authenticator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return mAuthenticator.getIBinder();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,34 +15,47 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.settings.users;
|
package com.android.settings.users;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.support.test.InstrumentationRegistry;
|
||||||
import android.support.test.filters.SmallTest;
|
import android.support.test.filters.SmallTest;
|
||||||
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
import android.support.test.uiautomator.UiDevice;
|
import android.support.test.uiautomator.UiDevice;
|
||||||
import android.support.test.uiautomator.UiObject;
|
import android.support.test.uiautomator.UiObject;
|
||||||
import android.support.test.uiautomator.UiSelector;
|
import android.support.test.uiautomator.UiSelector;
|
||||||
import android.support.test.uiautomator.UiScrollable;
|
import android.support.test.uiautomator.UiScrollable;
|
||||||
import android.test.InstrumentationTestCase;
|
import android.support.test.uiautomator.UiObjectNotFoundException;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public class UserSettingsTest extends InstrumentationTestCase {
|
public class UserSettingsTest {
|
||||||
|
|
||||||
private static final String USER_AND_ACCOUNTS = "Users & accounts";
|
private static final String SYSTEM = "System";
|
||||||
private static final String USERS = "Users";
|
private static final String ADVANCED = "Advanced";
|
||||||
|
private static final String USERS = "Multiple users";
|
||||||
private static final String EMERGNENCY_INFO = "Emergency information";
|
private static final String EMERGNENCY_INFO = "Emergency information";
|
||||||
private static final String ADD_USERS_WHEN_LOCKED = "Add users";
|
private static final String ADD_USERS_WHEN_LOCKED = "Add users";
|
||||||
|
private static final String SWITCH_USER_BUTTON = "com.android.systemui:id/multi_user_switch";
|
||||||
|
private static final String SETTINGS_BUTTON = "com.android.systemui:id/settings_button";
|
||||||
|
private static final String PRIMARY_USER = "Owner";
|
||||||
|
private static final String GUEST_USER = "Guest";
|
||||||
|
private static final String ADD_GUEST = "Add guest";
|
||||||
|
private static final String CONTINUE = "Yes, continue";
|
||||||
|
|
||||||
private UiDevice mDevice;
|
private UiDevice mDevice;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private String mTargetPackage;
|
private String mTargetPackage;
|
||||||
|
|
||||||
@Override
|
@Before
|
||||||
protected void setUp() throws Exception {
|
public void setUp() {
|
||||||
super.setUp();
|
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
|
||||||
mDevice = UiDevice.getInstance(getInstrumentation());
|
mContext = InstrumentationRegistry.getTargetContext();
|
||||||
mContext = getInstrumentation().getTargetContext();
|
|
||||||
mTargetPackage = mContext.getPackageName();
|
mTargetPackage = mContext.getPackageName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +64,8 @@ public class UserSettingsTest extends InstrumentationTestCase {
|
|||||||
launchUserSettings();
|
launchUserSettings();
|
||||||
UiObject emergencyInfoPreference =
|
UiObject emergencyInfoPreference =
|
||||||
mDevice.findObject(new UiSelector().text(EMERGNENCY_INFO));
|
mDevice.findObject(new UiSelector().text(EMERGNENCY_INFO));
|
||||||
assertFalse(emergencyInfoPreference.exists());
|
|
||||||
|
assertThat(emergencyInfoPreference.exists()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -59,7 +73,32 @@ public class UserSettingsTest extends InstrumentationTestCase {
|
|||||||
launchUserSettings();
|
launchUserSettings();
|
||||||
UiObject addUsersPreference =
|
UiObject addUsersPreference =
|
||||||
mDevice.findObject(new UiSelector().text(ADD_USERS_WHEN_LOCKED));
|
mDevice.findObject(new UiSelector().text(ADD_USERS_WHEN_LOCKED));
|
||||||
assertFalse(addUsersPreference.exists());
|
assertThat(addUsersPreference.exists()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUsersExistsOnSecondaryUser() throws Exception {
|
||||||
|
// switch to guest user
|
||||||
|
switchToOrCreateGuest();
|
||||||
|
// launch settings (launch from intent doesn't work, hence launch from quick settings)
|
||||||
|
mDevice.openQuickSettings();
|
||||||
|
mDevice.findObject(new UiSelector().resourceId(SETTINGS_BUTTON)).click();
|
||||||
|
// launch system settings and expand whole screen
|
||||||
|
final UiScrollable settings = new UiScrollable(
|
||||||
|
new UiSelector().packageName(mTargetPackage).scrollable(true));
|
||||||
|
final String titleSystem = SYSTEM;
|
||||||
|
settings.scrollTextIntoView(titleSystem);
|
||||||
|
mDevice.findObject(new UiSelector().text(titleSystem)).click();
|
||||||
|
mDevice.findObject(new UiSelector().text(ADVANCED)).click();
|
||||||
|
|
||||||
|
final boolean hasUsersSettings = mDevice.findObject(new UiSelector().text(USERS)).exists();
|
||||||
|
|
||||||
|
// switch back to primary user
|
||||||
|
mDevice.openQuickSettings();
|
||||||
|
mDevice.findObject(new UiSelector().resourceId(SWITCH_USER_BUTTON)).click();
|
||||||
|
mDevice.findObject(new UiSelector().text(PRIMARY_USER)).click();
|
||||||
|
|
||||||
|
assertThat(hasUsersSettings).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void launchSettings() {
|
private void launchSettings() {
|
||||||
@@ -67,17 +106,34 @@ public class UserSettingsTest extends InstrumentationTestCase {
|
|||||||
.addCategory(Intent.CATEGORY_LAUNCHER)
|
.addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
.setPackage(mTargetPackage)
|
.setPackage(mTargetPackage)
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
getInstrumentation().getContext().startActivity(settingsIntent);
|
mContext.startActivity(settingsIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void launchUserSettings() throws Exception {
|
private void launchUserSettings() throws Exception {
|
||||||
launchSettings();
|
launchSettings();
|
||||||
final UiScrollable settings = new UiScrollable(
|
final UiScrollable settings = new UiScrollable(
|
||||||
new UiSelector().packageName(mTargetPackage).scrollable(true));
|
new UiSelector().packageName(mTargetPackage).scrollable(true));
|
||||||
final String titleUsersAndAccounts = USER_AND_ACCOUNTS;
|
final String titleSystem = SYSTEM;
|
||||||
settings.scrollTextIntoView(titleUsersAndAccounts);
|
settings.scrollTextIntoView(titleSystem);
|
||||||
mDevice.findObject(new UiSelector().text(titleUsersAndAccounts)).click();
|
mDevice.findObject(new UiSelector().text(titleSystem)).click();
|
||||||
|
mDevice.findObject(new UiSelector().text(ADVANCED)).click();
|
||||||
mDevice.findObject(new UiSelector().text(USERS)).click();
|
mDevice.findObject(new UiSelector().text(USERS)).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void switchToOrCreateGuest() throws UiObjectNotFoundException {
|
||||||
|
mDevice.openQuickSettings();
|
||||||
|
mDevice.findObject(new UiSelector().resourceId(SWITCH_USER_BUTTON)).click();
|
||||||
|
// if no existing guest user, select "Add guest", otherwise select "Guest"
|
||||||
|
final UiObject addGuest = mDevice.findObject(new UiSelector().text(ADD_GUEST));
|
||||||
|
if (addGuest.exists()) {
|
||||||
|
addGuest.click();
|
||||||
|
mDevice.waitForIdle();
|
||||||
|
mDevice.pressBack();
|
||||||
|
} else {
|
||||||
|
mDevice.findObject(new UiSelector().text(GUEST_USER)).click();
|
||||||
|
mDevice.waitForIdle();
|
||||||
|
mDevice.findObject(new UiSelector().text(CONTINUE)).click();
|
||||||
|
mDevice.waitForIdle();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user