Merge "Align the search view with the setting items" into pi-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index feb1b05..c9045d8 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -739,6 +739,19 @@
</activity>
<activity
+ android:name="Settings$ZenModeBlockedEffectsSettingsActivity"
+ android:label="@string/zen_mode_what_to_block_title"
+ android:icon="@drawable/ic_settings_notifications"
+ android:exported="true"
+ android:taskAffinity="com.android.settings"
+ android:parentActivityName="Settings">
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.notification.ZenModeBlockedEffectsSetting" />
+ <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+ android:value="true" />
+ </activity>
+
+ <activity
android:name="Settings$ZenModeBehaviorSettingsActivity"
android:label="@string/zen_mode_behavior_settings_title"
android:icon="@drawable/ic_settings_notifications"
@@ -3218,7 +3231,7 @@
</activity>
<provider android:name=".slices.SettingsSliceProvider"
- android:authorities="com.android.settings.slices"
+ android:authorities="com.android.settings.slices;android.settings.slices"
android:exported="true">
</provider>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index d37091c..d0ddab6 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -96,8 +96,12 @@
<!-- For Search -->
<declare-styleable name="Preference">
+ <!-- Synonyms for search results -->
<attr name="keywords" format="string" />
+ <!-- Classname of a PreferenceController corresponding to the preference -->
<attr name="controller" format="string" />
+ <!-- {@code true} when the controller declared represents a slice from {@link android.app.SettingsSliceContract} -->
+ <attr name="platform_slice" format="boolean" />
</declare-styleable>
<!-- For DotsPageIndicator -->
diff --git a/res/values/bools.xml b/res/values/bools.xml
index 4665f2e..61a3c75 100644
--- a/res/values/bools.xml
+++ b/res/values/bools.xml
@@ -96,6 +96,9 @@
<!-- Whether device_administrators should be shown or not. -->
<bool name="config_show_device_administrators">true</bool>
+ <!-- Whether encryption_and_credentials_encryption_status should be shown or not. -->
+ <bool name="config_show_encryption_and_credentials_encryption_status">true</bool>
+
<!-- Whether premium_sms should be shown or not. -->
<bool name="config_show_premium_sms">true</bool>
@@ -153,6 +156,9 @@
<!-- Whether assist_and_voice_input should be shown or not. -->
<bool name="config_show_assist_and_voice_input">true</bool>
+ <!-- Whether reset_dashboard should be shown or not. -->
+ <bool name="config_show_reset_dashboard">true</bool>
+
<!-- Whether system_update_settings should be shown or not. -->
<bool name="config_show_system_update_settings">true</bool>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 39f641c..185732d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1676,10 +1676,10 @@
<string name="bluetooth_max_connected_audio_devices_string">Maximum connected Bluetooth audio devices</string>
<!-- Bluetooth developer settings: Maximum number of connected audio devices -->
<string name="bluetooth_max_connected_audio_devices_dialog_title">Select maximum number of connected Bluetooth audio devices</string>
- <!-- Bluetooth developer settings: Checkbox title for enabling Bluetooth receiving AVDTP delay reports -->
- <string name="bluetooth_enable_avdtp_delay_reports">Enable Bluetooth AVDTP delay reports</string>
- <!-- Bluetooth developer settings: Summary of checkbox for enabling Bluetooth receiving AVDTP delay reports -->
- <string name="bluetooth_enable_avdtp_delay_reports_summary">Allow receiving Bluetooth AVDTP delay reports</string>
+ <!-- Bluetooth developer settings: Checkbox title for disabling Bluetooth receiving AVDTP delay reports -->
+ <string name="bluetooth_disable_avdtp_delay_reports">Disable Bluetooth AVDTP delay reports</string>
+ <!-- Bluetooth developer settings: Summary of checkbox for disabling Bluetooth receiving AVDTP delay reports -->
+ <string name="bluetooth_disable_avdtp_delay_reports_summary">Disallow receiving Bluetooth AVDTP delay reports</string>
<!-- Wifi Display settings. The title of the screen. [CHAR LIMIT=40] -->
<string name="wifi_display_settings_title">Cast</string>
@@ -4177,10 +4177,6 @@
<string name="keyboard_shortcuts_helper">Keyboard shortcuts helper</string>
<!-- Summary text for the 'keyboard shortcuts helper' dialog. [CHAR LIMIT=100] -->
<string name="keyboard_shortcuts_helper_summary">Display available shortcuts</string>
- <!--
- Format string for a physical device in the form: InputMethodSubtype - InputMethodEditor.
- e.g. English (US) - X Keyboard -->
- <string name="physical_device_title" translatable="false"><xliff:g id="input_method_editor" example="X Keyboard">%1$s</xliff:g> - <xliff:g id="input_method_subtype" example="English (US)">%2$s</xliff:g></string>
<!-- Summary text for keyboards when no layout has been selected. [CHAR LIMIT=35] -->
<string name="default_keyboard_layout">Default</string>
@@ -6918,8 +6914,11 @@
<!-- Do not disturb: Title for the Do not Disturb dialog to turn on Do not disturb. [CHAR LIMIT=50]-->
<string name="zen_mode_settings_turn_on_dialog_title">Turn on Do Not Disturb</string>
- <!-- Do not disturb: Title for the behaviors option and associated settings page. [CHAR LIMIT=30] -->
- <string name="zen_mode_behavior_settings_title">Behavior</string>
+ <!-- Do not disturb: Title for the page describing what can bypass DND. [CHAR LIMIT=30] -->
+ <string name="zen_mode_behavior_settings_title">Exceptions</string>
+
+ <!-- Do not disturb: Title for the dnd duration setting (user can specify how long dnd will last when toggling dnd on from qs or settings) [CHAR LIMIT=30] -->
+ <string name="zen_mode_duration_settings_title">Duration</string>
<!-- Do not disturb: Instructions indicating what types of sounds can bypass DND. [CHAR LIMIT=52] -->
<string name="zen_mode_behavior_allow_title">Allow sounds and vibrations from</string>
@@ -6972,6 +6971,34 @@
<!-- Do not disturb: Subtitle for the Visual signals option to toggle on/off visual signals/alerts when the screen is on/when screen is off. [CHAR LIMIT=30] -->
<string name="zen_mode_visual_signals_settings_subtitle">Allow visual signals</string>
+ <!-- Do not disturb: what to block title [CHAR LIMIT = 60] -->
+ <string name="zen_mode_what_to_block_title">What to block</string>
+ <!-- Do not disturb: what to block > effects title [CHAR LIMIT = 60] -->
+ <string name="zen_mode_block_effects_title">When notifications arrive</string>
+ <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_block_effect_sound">Mute sound and vibration</string>
+ <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_block_effect_intent">Don\'t turn on screen</string>
+ <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_block_effect_light">Don\'t blink light</string>
+ <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_block_effect_peek">Don\'t pop notifications on screen</string>
+ <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_block_effect_status">Hide status bar icons</string>
+ <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_block_effect_badge">Hide notification dots</string>
+ <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_block_effect_ambient">Hide from ambient display</string>
+ <!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_block_effect_list">Hide from notification list</string>
+
+ <!-- Do not disturb: what to block summary, only sound and vibration -->
+ <string name="zen_mode_block_effect_summary_sound">Sound and vibration</string>
+ <!-- Do not disturb: what to block summary, sound vibration and some visual signals-->
+ <string name="zen_mode_block_effect_summary_some">Sound, vibration, and some visual signs of notifications</string>
+ <!-- Do not disturb: what to block summary, all effects -->
+ <string name="zen_mode_block_effect_summary_all">Sound, vibration, and visual signs of notifications</string>
+
<!-- Do not disturb: Button to add new automatic rule to DND. [CHAR LIMIT=30] -->
<string name="zen_mode_add">Add</string>
@@ -7002,8 +7029,8 @@
<!-- [CHAR LIMIT=20] Accessibility string for current zen mode and selected exit condition. A template that simply concatenates existing mode string and the current condition description. -->
<string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string>
- <!-- Sound settings screen, summary format of do not disturb when on. [CHAR LIMIT=NONE] -->
- <string name="zen_mode_sound_summary_on">On / <xliff:g name="dnd_summary" example="No sound except alarms and media">%1$s</xliff:g></string>
+ <!-- Sound settings screen, summary format of do not disturb when on with extra info. [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_sound_summary_on_with_info">On / <xliff:g name="dnd_summary" example="No sound except alarms and media">%1$s</xliff:g></string>
<!-- Sound settings screen, summary format of do not disturb when off with extra information. [CHAR LIMIT=NONE] -->
<string name="zen_mode_sound_summary_off_with_info">Off / <xliff:g name="dnd_summary" example="1 rule can turn on automatically">%1$s</xliff:g></string>
@@ -7011,6 +7038,24 @@
<!-- Sound settings screen, summary format of do not disturb when off with no extra information. [CHAR LIMIT=NONE] -->
<string name="zen_mode_sound_summary_off">Off</string>
+ <!-- Sound settings screen, summary format of do not disturb when on with no extra information. [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_sound_summary_on">On</string>
+
+ <!-- Do not disturb: Summary for zen mode duration setting indicating user will be prompted to set dnd duration whenever dnd is manually toggled on [CHAR LIMIT=NONE]-->
+ <string name="zen_mode_duration_summary_always_prompt">Ask every time (unless turned on automatically)</string>
+
+ <!-- Do not disturb: Summary for zen mode duration setting indicating how long dnd will last when dnd is manually toggled on [CHAR LIMIT=NONE] -->
+ <string name="zen_mode_duration_summary_forever">Until you turn off (unless turned on automatically)</string>
+
+ <!-- Do not disturb: Summary for zen mode duration setting indicating how long dnd will last when dnd is manually toggled on [CHAR LIMIT=NONE] -->
+ <plurals name="zen_mode_duration_summary_time_hours">
+ <item quantity="one">1 hour (unless turned on automatically)</item>
+ <item quantity="other"><xliff:g id="num_hours" example="3">%d</xliff:g> hours (unless turned on automatically)</item>
+ </plurals>
+
+ <!-- Do not disturb: Summary for zen mode duration setting indicating how long dnd will last when toggled on -->
+ <string name="zen_mode_duration_summary_time_minutes"><xliff:g id="num_minutes" example="5">%d</xliff:g> minutes (unless turned on automatically)</string>
+
<!-- Summary for the Sound Do not Disturb option when at least one automatic rules is enabled. [CHAR LIMIT=NONE]-->
<plurals name="zen_mode_sound_summary_summary_off_info">
<item quantity="one">1 rule can turn on automatically</item>
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index 36eab22..dda5655 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -26,7 +26,8 @@
android:icon="@drawable/ic_settings_bluetooth"
android:summary="@string/bluetooth_pref_summary"
android:order="-7"
- settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"/>
+ settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"
+ settings:platform_slice="true"/>
<SwitchPreference
android:key="toggle_nfc"
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 571f38e..282a5121 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -264,9 +264,9 @@
android:summary="@string/bluetooth_disable_inband_ringing_summary" />
<SwitchPreference
- android:key="bluetooth_enable_avdtp_delay_reports"
- android:title="@string/bluetooth_enable_avdtp_delay_reports"
- android:summary="@string/bluetooth_enable_avdtp_delay_reports_summary"/>
+ android:key="bluetooth_disable_avdtp_delay_reports"
+ android:title="@string/bluetooth_disable_avdtp_delay_reports"
+ android:summary="@string/bluetooth_disable_avdtp_delay_reports_summary"/>
<ListPreference
android:key="bluetooth_select_avrcp_version"
diff --git a/res/xml/system_dashboard_fragment.xml b/res/xml/system_dashboard_fragment.xml
index d8459dd..c3f15b9 100644
--- a/res/xml/system_dashboard_fragment.xml
+++ b/res/xml/system_dashboard_fragment.xml
@@ -46,7 +46,8 @@
android:summary="@string/reset_dashboard_summary"
android:icon="@drawable/ic_restore"
android:order="-50"
- android:fragment="com.android.settings.system.ResetDashboardFragment" />
+ android:fragment="com.android.settings.system.ResetDashboardFragment"
+ settings:controller="com.android.settings.system.ResetPreferenceController"/>
<!-- System updates -->
<Preference
diff --git a/res/xml/zen_mode_behavior_settings.xml b/res/xml/zen_mode_behavior_settings.xml
index 084b78d..8426d91 100644
--- a/res/xml/zen_mode_behavior_settings.xml
+++ b/res/xml/zen_mode_behavior_settings.xml
@@ -19,71 +19,51 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="zen_mode_behavior_settings_page"
- android:title="@string/zen_mode_behavior_settings_title"
- settings:initialExpandedChildrenCount="8">
+ android:title="@string/zen_mode_behavior_settings_title" >
- <PreferenceCategory
- android:title="@string/zen_mode_behavior_allow_title"
- android:key="zen_mode_behavior_allow_preferences">
+ <!-- Alarms -->
+ <SwitchPreference
+ android:key="zen_mode_alarms"
+ android:title="@string/zen_mode_alarms"/>
- <!-- Alarms -->
- <SwitchPreference
- android:key="zen_mode_alarms"
- android:title="@string/zen_mode_alarms"/>
+ <!-- Media -->
+ <SwitchPreference
+ android:key="zen_mode_media"
+ android:title="@string/zen_mode_media"/>
- <!-- Media -->
- <SwitchPreference
- android:key="zen_mode_media"
- android:title="@string/zen_mode_media"/>
+ <!-- System -->
+ <SwitchPreference
+ android:key="zen_mode_system"
+ android:title="@string/zen_mode_system"/>
- <!-- System -->
- <SwitchPreference
- android:key="zen_mode_system"
- android:title="@string/zen_mode_system"/>
+ <!-- Reminders -->
+ <SwitchPreference
+ android:key="zen_mode_reminders"
+ android:title="@string/zen_mode_reminders"/>
- <!-- Reminders -->
- <SwitchPreference
- android:key="zen_mode_reminders"
- android:title="@string/zen_mode_reminders"/>
+ <!-- Events -->
+ <SwitchPreference
+ android:key="zen_mode_events"
+ android:title="@string/zen_mode_events"/>
- <!-- Events -->
- <SwitchPreference
- android:key="zen_mode_events"
- android:title="@string/zen_mode_events"/>
+ <!-- Messages -->
+ <ListPreference
+ android:key="zen_mode_messages"
+ android:title="@string/zen_mode_messages"
+ android:entries="@array/zen_mode_contacts_entries"
+ android:entryValues="@array/zen_mode_contacts_values"/>
- <!-- Messages -->
- <ListPreference
- android:key="zen_mode_messages"
- android:title="@string/zen_mode_messages"
- android:entries="@array/zen_mode_contacts_entries"
- android:entryValues="@array/zen_mode_contacts_values"/>
+ <!-- Calls -->
+ <ListPreference
+ android:key="zen_mode_calls"
+ android:title="@string/zen_mode_calls"
+ android:entries="@array/zen_mode_contacts_entries"
+ android:entryValues="@array/zen_mode_contacts_values"/>
- <!-- Calls -->
- <ListPreference
- android:key="zen_mode_calls"
- android:title="@string/zen_mode_calls"
- android:entries="@array/zen_mode_contacts_entries"
- android:entryValues="@array/zen_mode_contacts_values"/>
-
- <!-- Repeat callers -->
- <SwitchPreference
- android:key="zen_mode_repeat_callers"
- android:title="@string/zen_mode_repeat_callers" />
-
- </PreferenceCategory>
-
- <PreferenceCategory
- android:title="@string/zen_mode_visual_signals_settings_subtitle"
- android:key="zen_mode_visual_signals_preferences">
-
- <SwitchPreference android:key="zen_mode_screen_on"
- android:title="@string/zen_mode_screen_on"
- android:summary="@string/zen_mode_screen_on_summary" />
-
- <SwitchPreference android:key="zen_mode_screen_off"
- android:title="@string/zen_mode_screen_off"
- android:summary="@string/zen_mode_screen_off_summary" />
- </PreferenceCategory>
+ <!-- Repeat callers -->
+ <SwitchPreference
+ android:key="zen_mode_repeat_callers"
+ android:title="@string/zen_mode_repeat_callers" />
<com.android.settingslib.widget.FooterPreference />
diff --git a/res/xml/zen_mode_block_settings.xml b/res/xml/zen_mode_block_settings.xml
new file mode 100644
index 0000000..ce33e97
--- /dev/null
+++ b/res/xml/zen_mode_block_settings.xml
@@ -0,0 +1,61 @@
+<?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"
+ android:key="zen_mode_block_settings_page">
+
+ <!-- sound vibration -->
+ <CheckBoxPreference
+ android:key="zen_effect_sound"
+ android:title="@string/zen_mode_block_effect_sound"
+ android:enabled="false" />
+
+ <PreferenceCategory
+ android:title="@string/zen_mode_block_effects_title"
+ android:key="zen_mode_block_vis_effects">
+
+ <CheckBoxPreference
+ android:key="zen_effect_intent"
+ android:title="@string/zen_mode_block_effect_intent" />
+
+ <CheckBoxPreference
+ android:key="zen_effect_light"
+ android:title="@string/zen_mode_block_effect_light" />
+
+ <CheckBoxPreference
+ android:key="zen_effect_peek"
+ android:title="@string/zen_mode_block_effect_peek" />
+
+ <CheckBoxPreference
+ android:key="zen_effect_status"
+ android:title="@string/zen_mode_block_effect_status" />
+
+ <CheckBoxPreference
+ android:key="zen_effect_badge"
+ android:title="@string/zen_mode_block_effect_badge" />
+
+ <CheckBoxPreference
+ android:key="zen_effect_ambient"
+ android:title="@string/zen_mode_block_effect_ambient" />
+
+ <CheckBoxPreference
+ android:key="zen_effect_list"
+ android:title="@string/zen_mode_block_effect_list" />
+ </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/res/xml/zen_mode_settings.xml b/res/xml/zen_mode_settings.xml
index ca8ad10..65fb7ab 100644
--- a/res/xml/zen_mode_settings.xml
+++ b/res/xml/zen_mode_settings.xml
@@ -19,12 +19,23 @@
android:key="zen_mode_settings"
android:title="@string/zen_mode_settings_title">
- <!-- Priority behavior settings -->
+ <!-- What to block (effects) -->
+ <Preference
+ android:key="zen_mode_block_effects_settings"
+ android:title="@string/zen_mode_what_to_block_title"
+ android:fragment="com.android.settings.notification.ZenModeBlockedEffectsSettings" />
+
+ <!-- Behavior settings (exceptions) -->
<Preference
android:key="zen_mode_behavior_settings"
android:title="@string/zen_mode_behavior_settings_title"
android:fragment="com.android.settings.notification.ZenModeBehaviorSettings" />
+ <!-- DND duration settings -->
+ <Preference
+ android:key="zen_mode_duration_settings"
+ android:title="@string/zen_mode_duration_settings_title" />
+
<!-- Automatic rules -->
<Preference
android:key="zen_mode_automation_settings"
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 4baa77b..03853d1 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -100,6 +100,7 @@
public static class PrintJobSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeBehaviorSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class ZenModeBlockedEffectsSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeAutomationSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeScheduleRuleSettingsActivity extends SettingsActivity { /* empty */ }
public static class ZenModeEventRuleSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/bluetooth/BluetoothFilesPreferenceController.java b/src/com/android/settings/bluetooth/BluetoothFilesPreferenceController.java
index 1ecfed4..6fbb84a 100644
--- a/src/com/android/settings/bluetooth/BluetoothFilesPreferenceController.java
+++ b/src/com/android/settings/bluetooth/BluetoothFilesPreferenceController.java
@@ -16,12 +16,14 @@
package com.android.settings.bluetooth;
+import android.content.pm.PackageManager;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -30,7 +32,7 @@
/**
* Controller that shows received files
*/
-public class BluetoothFilesPreferenceController extends AbstractPreferenceController
+public class BluetoothFilesPreferenceController extends BasePreferenceController
implements PreferenceControllerMixin {
private static final String TAG = "BluetoothFilesPrefCtrl";
@@ -47,13 +49,15 @@
private MetricsFeatureProvider mMetricsFeatureProvider;
public BluetoothFilesPreferenceController(Context context) {
- super(context);
+ super(context, KEY_RECEIVED_FILES);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
@Override
- public boolean isAvailable() {
- return true;
+ public int getAvailabilityStatus() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
+ ? AVAILABLE
+ : DISABLED_UNSUPPORTED;
}
@Override
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
index 0e556c4..1a64f26 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
+import android.util.Log;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
@@ -71,7 +72,10 @@
@Override
public void onStart() {
super.onStart();
-
+ if (mLocalManager == null){
+ Log.e(TAG, "Bluetooth is not supported on this device");
+ return;
+ }
updateBluetooth();
mAvailableDevicesCategory.setProgress(mLocalAdapter.isDiscovering());
}
@@ -89,7 +93,10 @@
@Override
public void onStop() {
super.onStop();
-
+ if (mLocalManager == null){
+ Log.e(TAG, "Bluetooth is not supported on this device");
+ return;
+ }
// Make the device only visible to connected devices.
mAlwaysDiscoverable.stop();
disableScanning();
diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java b/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java
index 3d5d0e5..c77a735 100644
--- a/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java
+++ b/src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java
@@ -15,15 +15,18 @@
*/
package com.android.settings.connecteddevice;
+import android.content.pm.PackageManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.connecteddevice.usb.ConnectedUsbDeviceUpdater;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.bluetooth.ConnectedBluetoothDeviceUpdater;
+import com.android.settings.search.ResultPayload;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -35,7 +38,7 @@
* Controller to maintain the {@link android.support.v7.preference.PreferenceGroup} for all
* connected devices. It uses {@link DevicePreferenceCallback} to add/remove {@link Preference}
*/
-public class ConnectedDeviceGroupController extends AbstractPreferenceController
+public class ConnectedDeviceGroupController extends BasePreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop,
DevicePreferenceCallback {
@@ -47,7 +50,7 @@
private ConnectedUsbDeviceUpdater mConnectedUsbDeviceUpdater;
public ConnectedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle) {
- super(fragment.getContext());
+ super(fragment.getContext(), KEY);
init(lifecycle, new ConnectedBluetoothDeviceUpdater(fragment, this),
new ConnectedUsbDeviceUpdater(fragment, this));
}
@@ -56,7 +59,7 @@
ConnectedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle,
BluetoothDeviceUpdater bluetoothDeviceUpdater,
ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater) {
- super(fragment.getContext());
+ super(fragment.getContext(), KEY);
init(lifecycle, bluetoothDeviceUpdater, connectedUsbDeviceUpdater);
}
@@ -75,17 +78,21 @@
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
- mPreferenceGroup.setVisible(false);
+ if (isAvailable()) {
+ mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
+ mPreferenceGroup.setVisible(false);
- mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
- mBluetoothDeviceUpdater.forceUpdate();
- mConnectedUsbDeviceUpdater.initUsbPreference(screen.getContext());
+ mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
+ mBluetoothDeviceUpdater.forceUpdate();
+ mConnectedUsbDeviceUpdater.initUsbPreference(screen.getContext());
+ }
}
@Override
- public boolean isAvailable() {
- return true;
+ public int getAvailabilityStatus() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
+ ? AVAILABLE
+ : DISABLED_UNSUPPORTED;
}
@Override
@@ -111,7 +118,7 @@
private void init(Lifecycle lifecycle, BluetoothDeviceUpdater bluetoothDeviceUpdater,
ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater) {
- if (lifecycle != null) {
+ if (lifecycle != null && isAvailable()) {
lifecycle.addObserver(this);
}
mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
diff --git a/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java b/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java
index 7445047..da38d9f 100644
--- a/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java
+++ b/src/com/android/settings/connecteddevice/SavedDeviceGroupController.java
@@ -15,6 +15,7 @@
*/
package com.android.settings.connecteddevice;
+import android.content.pm.PackageManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
@@ -22,6 +23,7 @@
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.bluetooth.SavedBluetoothDeviceUpdater;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -34,7 +36,7 @@
* Controller to maintain the {@link PreferenceGroup} for all
* saved devices. It uses {@link DevicePreferenceCallback} to add/remove {@link Preference}
*/
-public class SavedDeviceGroupController extends AbstractPreferenceController
+public class SavedDeviceGroupController extends BasePreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop,
DevicePreferenceCallback {
@@ -45,14 +47,14 @@
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
public SavedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle) {
- super(fragment.getContext());
+ super(fragment.getContext(), KEY);
init(lifecycle, new SavedBluetoothDeviceUpdater(fragment, SavedDeviceGroupController.this));
}
@VisibleForTesting
SavedDeviceGroupController(DashboardFragment fragment, Lifecycle lifecycle,
BluetoothDeviceUpdater bluetoothDeviceUpdater) {
- super(fragment.getContext());
+ super(fragment.getContext(), KEY);
init(lifecycle, bluetoothDeviceUpdater);
}
@@ -68,15 +70,19 @@
@Override
public void displayPreference(PreferenceScreen screen) {
- mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
- mPreferenceGroup.setVisible(false);
- mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
- mBluetoothDeviceUpdater.forceUpdate();
+ if (isAvailable()) {
+ mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
+ mPreferenceGroup.setVisible(false);
+ mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
+ mBluetoothDeviceUpdater.forceUpdate();
+ }
}
@Override
- public boolean isAvailable() {
- return true;
+ public int getAvailabilityStatus() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
+ ? AVAILABLE
+ : DISABLED_UNSUPPORTED;
}
@Override
@@ -101,7 +107,7 @@
}
private void init(Lifecycle lifecycle, BluetoothDeviceUpdater bluetoothDeviceUpdater) {
- if (lifecycle != null) {
+ if (lifecycle != null && isAvailable()) {
lifecycle.addObserver(this);
}
mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
diff --git a/src/com/android/settings/core/PreferenceXmlParserUtils.java b/src/com/android/settings/core/PreferenceXmlParserUtils.java
index 7afe8d8..8620dce 100644
--- a/src/com/android/settings/core/PreferenceXmlParserUtils.java
+++ b/src/com/android/settings/core/PreferenceXmlParserUtils.java
@@ -76,6 +76,7 @@
int FLAG_NEED_PREF_TITLE = 1 << 4;
int FLAG_NEED_PREF_SUMMARY = 1 << 5;
int FLAG_NEED_PREF_ICON = 1 << 6;
+ int FLAG_NEED_PLATFORM_SLICE_FLAG = 1 << 7;
}
public static final String METADATA_PREF_TYPE = "type";
@@ -84,35 +85,48 @@
public static final String METADATA_TITLE = "title";
public static final String METADATA_SUMMARY = "summary";
public static final String METADATA_ICON = "icon";
+ public static final String METADATA_PLATFORM_SLICE_FLAG = "platform_slice";
private static final String ENTRIES_SEPARATOR = "|";
+ /**
+ * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_KEY} instead.
+ */
+ @Deprecated
public static String getDataKey(Context context, AttributeSet attrs) {
- return getData(context, attrs,
+ return getStringData(context, attrs,
com.android.internal.R.styleable.Preference,
com.android.internal.R.styleable.Preference_key);
}
+ /**
+ * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_TITLE} instead.
+ */
+ @Deprecated
public static String getDataTitle(Context context, AttributeSet attrs) {
- return getData(context, attrs,
+ return getStringData(context, attrs,
com.android.internal.R.styleable.Preference,
com.android.internal.R.styleable.Preference_title);
}
+ /**
+ * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_SUMMARY} instead.
+ */
+ @Deprecated
public static String getDataSummary(Context context, AttributeSet attrs) {
- return getData(context, attrs,
+ return getStringData(context, attrs,
com.android.internal.R.styleable.Preference,
com.android.internal.R.styleable.Preference_summary);
}
public static String getDataSummaryOn(Context context, AttributeSet attrs) {
- return getData(context, attrs,
+ return getStringData(context, attrs,
com.android.internal.R.styleable.CheckBoxPreference,
com.android.internal.R.styleable.CheckBoxPreference_summaryOn);
}
public static String getDataSummaryOff(Context context, AttributeSet attrs) {
- return getData(context, attrs,
+ return getStringData(context, attrs,
com.android.internal.R.styleable.CheckBoxPreference,
com.android.internal.R.styleable.CheckBoxPreference_summaryOff);
}
@@ -124,13 +138,23 @@
}
public static String getDataKeywords(Context context, AttributeSet attrs) {
- return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_keywords);
+ return getStringData(context, attrs, R.styleable.Preference,
+ R.styleable.Preference_keywords);
}
+ /**
+ * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_CONTROLLER} instead.
+ */
+ @Deprecated
public static String getController(Context context, AttributeSet attrs) {
- return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_controller);
+ return getStringData(context, attrs, R.styleable.Preference,
+ R.styleable.Preference_controller);
}
+ /**
+ * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_ICON} instead.
+ */
+ @Deprecated
public static int getDataIcon(Context context, AttributeSet attrs) {
final TypedArray ta = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.Preference);
@@ -176,25 +200,35 @@
}
final Bundle preferenceMetadata = new Bundle();
final AttributeSet attrs = Xml.asAttributeSet(parser);
+ final TypedArray preferenceAttributes = context.obtainStyledAttributes(attrs,
+ R.styleable.Preference);
+
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TYPE)) {
preferenceMetadata.putString(METADATA_PREF_TYPE, nodeName);
}
if (hasFlag(flags, MetadataFlag.FLAG_NEED_KEY)) {
- preferenceMetadata.putString(METADATA_KEY, getDataKey(context, attrs));
+ preferenceMetadata.putString(METADATA_KEY, getKey(preferenceAttributes));
}
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_CONTROLLER)) {
- preferenceMetadata.putString(METADATA_CONTROLLER, getController(context, attrs));
+ preferenceMetadata.putString(METADATA_CONTROLLER,
+ getController(preferenceAttributes));
}
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TITLE)) {
- preferenceMetadata.putString(METADATA_TITLE, getDataTitle(context, attrs));
+ preferenceMetadata.putString(METADATA_TITLE, getTitle(preferenceAttributes));
}
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_SUMMARY)) {
- preferenceMetadata.putString(METADATA_SUMMARY, getDataSummary(context, attrs));
+ preferenceMetadata.putString(METADATA_SUMMARY, getSummary(preferenceAttributes));
}
if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_ICON)) {
- preferenceMetadata.putInt(METADATA_ICON, getDataIcon(context, attrs));
+ preferenceMetadata.putInt(METADATA_ICON, getIcon(preferenceAttributes));
+ }
+ if (hasFlag(flags, MetadataFlag.FLAG_NEED_PLATFORM_SLICE_FLAG)) {
+ preferenceMetadata.putBoolean(METADATA_PLATFORM_SLICE_FLAG,
+ getPlatformSlice(preferenceAttributes));
}
metadata.add(preferenceMetadata);
+
+ preferenceAttributes.recycle();
} while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth));
parser.close();
@@ -205,12 +239,16 @@
* Returns the fragment name if this preference launches a child fragment.
*/
public static String getDataChildFragment(Context context, AttributeSet attrs) {
- return getData(context, attrs, R.styleable.Preference,
+ return getStringData(context, attrs, R.styleable.Preference,
R.styleable.Preference_android_fragment);
}
+ /**
+ * Call {@link #extractMetadata(Context, int, int)} with a {@link MetadataFlag} instead.
+ */
+ @Deprecated
@Nullable
- private static String getData(Context context, AttributeSet set, int[] attrs, int resId) {
+ private static String getStringData(Context context, AttributeSet set, int[] attrs, int resId) {
final TypedArray ta = context.obtainStyledAttributes(set, attrs);
String data = ta.getString(resId);
ta.recycle();
@@ -243,4 +281,28 @@
}
return result.toString();
}
+
+ private static String getKey(TypedArray styledAttributes) {
+ return styledAttributes.getString(com.android.internal.R.styleable.Preference_key);
+ }
+
+ private static String getTitle(TypedArray styledAttributes) {
+ return styledAttributes.getString(com.android.internal.R.styleable.Preference_title);
+ }
+
+ private static String getSummary(TypedArray styledAttributes) {
+ return styledAttributes.getString(com.android.internal.R.styleable.Preference_summary);
+ }
+
+ private static String getController(TypedArray styledAttributes) {
+ return styledAttributes.getString(R.styleable.Preference_controller);
+ }
+
+ private static int getIcon(TypedArray styledAttributes) {
+ return styledAttributes.getResourceId(com.android.internal.R.styleable.Icon_icon, 0);
+ }
+
+ private static boolean getPlatformSlice(TypedArray styledAttributes) {
+ return styledAttributes.getBoolean(R.styleable.Preference_platform_slice, false /* def */);
+ }
}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index f9c7847..0cbc539 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -105,6 +105,7 @@
import com.android.settings.notification.ZenAccessSettings;
import com.android.settings.notification.ZenModeAutomationSettings;
import com.android.settings.notification.ZenModeBehaviorSettings;
+import com.android.settings.notification.ZenModeBlockedEffectsSettings;
import com.android.settings.notification.ZenModeEventRuleSettings;
import com.android.settings.notification.ZenModeScheduleRuleSettings;
import com.android.settings.notification.ZenModeSettings;
@@ -220,6 +221,7 @@
ZenModeBehaviorSettings.class.getName(),
ZenModeScheduleRuleSettings.class.getName(),
ZenModeEventRuleSettings.class.getName(),
+ ZenModeBlockedEffectsSettings.class.getName(),
ProcessStatsUi.class.getName(),
AdvancedPowerUsageDetail.class.getName(),
ProcessStatsSummary.class.getName(),
diff --git a/src/com/android/settings/datetime/timezone/FixedOffsetPreferenceController.java b/src/com/android/settings/datetime/timezone/FixedOffsetPreferenceController.java
index 16c1f19..234e7db 100644
--- a/src/com/android/settings/datetime/timezone/FixedOffsetPreferenceController.java
+++ b/src/com/android/settings/datetime/timezone/FixedOffsetPreferenceController.java
@@ -17,7 +17,8 @@
package com.android.settings.datetime.timezone;
import android.content.Context;
-import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
public class FixedOffsetPreferenceController extends BaseTimeZonePreferenceController {
@@ -31,8 +32,18 @@
@Override
public CharSequence getSummary() {
- // This is a Spannable object, which contains TTS span. It shouldn't be converted to String.
- return mTimeZoneInfo == null ? "" : mTimeZoneInfo.getGmtOffset();
+ if (mTimeZoneInfo == null) {
+ return "";
+ }
+
+ String standardName = mTimeZoneInfo.getStandardName();
+ if (standardName == null) {
+ return mTimeZoneInfo.getGmtOffset();
+ } else {
+ // GmtOffset is Spannable, which contains TTS span. It shouldn't be converted to String.
+ return SpannableUtil.getResourcesText(mContext.getResources(),
+ R.string.zone_info_offset_and_name, mTimeZoneInfo.getGmtOffset(), standardName);
+ }
}
public void setTimeZoneInfo(TimeZoneInfo timeZoneInfo) {
diff --git a/src/com/android/settings/development/BluetoothDelayReportsPreferenceController.java b/src/com/android/settings/development/BluetoothDelayReportsPreferenceController.java
index 0858555..6c7a7dd 100644
--- a/src/com/android/settings/development/BluetoothDelayReportsPreferenceController.java
+++ b/src/com/android/settings/development/BluetoothDelayReportsPreferenceController.java
@@ -28,11 +28,11 @@
public class BluetoothDelayReportsPreferenceController extends DeveloperOptionsPreferenceController
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
- private static final String BLUETOOTH_ENABLE_AVDTP_DELAY_REPORT_KEY =
- "bluetooth_enable_avdtp_delay_reports";
+ private static final String BLUETOOTH_DISABLE_AVDTP_DELAY_REPORT_KEY =
+ "bluetooth_disable_avdtp_delay_reports";
@VisibleForTesting
- static final String BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY =
- "persist.bluetooth.enabledelayreports";
+ static final String BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY =
+ "persist.bluetooth.disabledelayreports";
public BluetoothDelayReportsPreferenceController(Context context) {
super(context);
@@ -40,22 +40,22 @@
@Override
public String getPreferenceKey() {
- return BLUETOOTH_ENABLE_AVDTP_DELAY_REPORT_KEY;
+ return BLUETOOTH_DISABLE_AVDTP_DELAY_REPORT_KEY;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- final boolean isEnabled = (Boolean) newValue;
- SystemProperties.set(BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY,
- isEnabled ? "true" : "false");
+ final boolean isDisabled = (Boolean) newValue;
+ SystemProperties.set(BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY,
+ isDisabled ? "true" : "false");
return true;
}
@Override
public void updateState(Preference preference) {
- final boolean isEnabled = SystemProperties.getBoolean(
- BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
- ((SwitchPreference) mPreference).setChecked(isEnabled);
+ final boolean isDisabled = SystemProperties.getBoolean(
+ BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
+ ((SwitchPreference) mPreference).setChecked(isDisabled);
}
@Override
@@ -63,7 +63,7 @@
super.onDeveloperOptionsSwitchDisabled();
// the default setting for this preference is the disabled state
((SwitchPreference) mPreference).setChecked(false);
- SystemProperties.set(BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY, "false");
+ SystemProperties.set(BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, "false");
}
}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceController.java
index 05b3503..34d354f 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceController.java
@@ -25,6 +25,7 @@
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
+import android.util.Log;
import com.android.settings.R;
import com.android.settings.Utils;
@@ -40,6 +41,7 @@
*/
public class AutoBatterySeekBarPreferenceController extends BasePreferenceController implements
LifecycleObserver, OnStart, OnStop, SeekBarPreference.OnPreferenceChangeListener {
+ private static final String TAG = "AutoBatterySeekBarPreferenceController";
@VisibleForTesting
static final String KEY_AUTO_BATTERY_SEEK_BAR = "battery_saver_seek_bar";
private final int mDefWarnLevel;
@@ -61,6 +63,7 @@
super.displayPreference(screen);
mPreference = (SeekBarPreference) screen.findPreference(
KEY_AUTO_BATTERY_SEEK_BAR);
+ mPreference.setContinuousUpdates(true);
updatePreference(mPreference);
}
@@ -96,6 +99,24 @@
@VisibleForTesting
void updatePreference(Preference preference) {
final ContentResolver contentResolver = mContext.getContentResolver();
+
+ // Override the max value with LOW_POWER_MODE_TRIGGER_LEVEL_MAX, if set.
+ final int maxLevel = Settings.Global.getInt(contentResolver,
+ Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 0);
+ if (maxLevel > 0) {
+ if (!(preference instanceof SeekBarPreference)) {
+ Log.e(TAG, "Unexpected preference class: " + preference.getClass());
+ } else {
+ final SeekBarPreference seekBarPreference = (SeekBarPreference) preference;
+ if (maxLevel < seekBarPreference.getMin()) {
+ Log.e(TAG, "LOW_POWER_MODE_TRIGGER_LEVEL_MAX too low; ignored.");
+ } else {
+ seekBarPreference.setMax(maxLevel);
+ }
+ }
+ }
+
+ // Set the current value.
final int level = Settings.Global.getInt(contentResolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, mDefWarnLevel);
if (level == 0) {
@@ -109,7 +130,7 @@
}
/**
- * Observer that listens to change from {@link Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL}
+ * Observer that listens to change from {@link Settings.Global#LOW_POWER_MODE_TRIGGER_LEVEL}
*/
private final class AutoBatterySaverSettingObserver extends ContentObserver {
private final Uri mUri = Settings.Global.getUriFor(
diff --git a/src/com/android/settings/fuelgauge/batterytip/AppInfo.java b/src/com/android/settings/fuelgauge/batterytip/AppInfo.java
index dc6ba25..9e8aba3 100644
--- a/src/com/android/settings/fuelgauge/batterytip/AppInfo.java
+++ b/src/com/android/settings/fuelgauge/batterytip/AppInfo.java
@@ -20,9 +20,12 @@
import android.os.Parcelable;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
+import android.util.ArraySet;
import com.android.settings.fuelgauge.anomaly.Anomaly;
+import java.util.Objects;
+
/**
* Model class stores app info(e.g. package name, type..) that used in battery tip
*/
@@ -32,13 +35,13 @@
* Anomaly type of the app
* @see Anomaly.AnomalyType
*/
- public final int anomalyType;
+ public final ArraySet<Integer> anomalyTypes;
public final long screenOnTimeMs;
public final int uid;
private AppInfo(AppInfo.Builder builder) {
packageName = builder.mPackageName;
- anomalyType = builder.mAnomalyType;
+ anomalyTypes = builder.mAnomalyTypes;
screenOnTimeMs = builder.mScreenOnTimeMs;
uid = builder.mUid;
}
@@ -46,7 +49,7 @@
@VisibleForTesting
AppInfo(Parcel in) {
packageName = in.readString();
- anomalyType = in.readInt();
+ anomalyTypes = (ArraySet<Integer>) in.readArraySet(null /* loader */);
screenOnTimeMs = in.readLong();
uid = in.readInt();
}
@@ -64,14 +67,14 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(packageName);
- dest.writeInt(anomalyType);
+ dest.writeArraySet(anomalyTypes);
dest.writeLong(screenOnTimeMs);
dest.writeInt(uid);
}
@Override
public String toString() {
- return "packageName=" + packageName + ",anomalyType=" + anomalyType + ",screenTime="
+ return "packageName=" + packageName + ",anomalyTypes=" + anomalyTypes + ",screenTime="
+ screenOnTimeMs;
}
@@ -85,7 +88,7 @@
}
AppInfo other = (AppInfo) obj;
- return anomalyType == other.anomalyType
+ return Objects.equals(anomalyTypes, other.anomalyTypes)
&& uid == other.uid
&& screenOnTimeMs == other.screenOnTimeMs
&& TextUtils.equals(packageName, other.packageName);
@@ -102,13 +105,13 @@
};
public static final class Builder {
- private int mAnomalyType;
+ private ArraySet<Integer> mAnomalyTypes = new ArraySet<>();
private String mPackageName;
private long mScreenOnTimeMs;
private int mUid;
- public Builder setAnomalyType(int type) {
- mAnomalyType = type;
+ public Builder addAnomalyType(int type) {
+ mAnomalyTypes.add(type);
return this;
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java b/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
index 798c8c6..58e9d03 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
@@ -32,10 +32,12 @@
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
+import android.util.ArrayMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
/**
* Database manager for battery data. Now it only contains anomaly data stored in {@link AppInfo}.
@@ -88,20 +90,30 @@
try (SQLiteDatabase db = mDatabaseHelper.getReadableDatabase()) {
final String[] projection = {PACKAGE_NAME, ANOMALY_TYPE, UID};
final String orderBy = AnomalyDatabaseHelper.AnomalyColumns.TIME_STAMP_MS + " DESC";
+ final Map<Integer, AppInfo.Builder> mAppInfoBuilders = new ArrayMap<>();
+ final String selection = TIME_STAMP_MS + " > ? AND " + ANOMALY_STATE + " = ? ";
+ final String[] selectionArgs = new String[]{String.valueOf(timestampMsAfter),
+ String.valueOf(state)};
- try (Cursor cursor = db.query(TABLE_ANOMALY, projection,
- TIME_STAMP_MS + " > ? AND " + ANOMALY_STATE + " = ? ",
- new String[]{String.valueOf(timestampMsAfter), String.valueOf(state)}, null,
- null, orderBy)) {
+ try (Cursor cursor = db.query(TABLE_ANOMALY, projection, selection, selectionArgs,
+ null /* groupBy */, null /* having */, orderBy)) {
while (cursor.moveToNext()) {
- AppInfo appInfo = new AppInfo.Builder()
- .setPackageName(cursor.getString(cursor.getColumnIndex(PACKAGE_NAME)))
- .setAnomalyType(cursor.getInt(cursor.getColumnIndex(ANOMALY_TYPE)))
- .setUid(cursor.getInt(cursor.getColumnIndex(UID)))
- .build();
- appInfos.add(appInfo);
+ final int uid = cursor.getInt(cursor.getColumnIndex(UID));
+ if (!mAppInfoBuilders.containsKey(uid)) {
+ final AppInfo.Builder builder = new AppInfo.Builder()
+ .setUid(uid)
+ .setPackageName(
+ cursor.getString(cursor.getColumnIndex(PACKAGE_NAME)));
+ mAppInfoBuilders.put(uid, builder);
+ }
+ mAppInfoBuilders.get(uid).addAnomalyType(
+ cursor.getInt(cursor.getColumnIndex(ANOMALY_TYPE)));
}
}
+
+ for (Integer uid : mAppInfoBuilders.keySet()) {
+ appInfos.add(mAppInfoBuilders.get(uid).build());
+ }
}
return appInfos;
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
index 2702bb6..d2af589 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
@@ -104,9 +104,7 @@
final Preference preference = batteryTip.buildPreference(mPrefContext);
mBatteryTipMap.put(preference.getKey(), batteryTip);
mPreferenceGroup.addPreference(preference);
- mMetricsFeatureProvider.action(mContext,
- MetricsProto.MetricsEvent.ACTION_BATTERY_TIP_SHOWN,
- batteryTip.getType());
+ batteryTip.log(mContext, mMetricsFeatureProvider);
break;
}
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java
index 5c0147a..5ff5430 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java
@@ -16,8 +16,6 @@
package com.android.settings.fuelgauge.batterytip;
-import android.app.Fragment;
-
import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.fuelgauge.batterytip.actions.BatterySaverAction;
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
index f252638..3c3a5c0 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
@@ -25,6 +25,8 @@
import android.support.v7.preference.Preference;
import android.util.SparseIntArray;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -123,6 +125,11 @@
*/
public abstract void updateState(BatteryTip tip);
+ /**
+ * Log the battery tip
+ */
+ public abstract void log(Context context, MetricsFeatureProvider metricsFeatureProvider);
+
public Preference buildPreference(Context context) {
Preference preference = new Preference(context);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java
index 7b8f624..908b873 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java
@@ -19,7 +19,9 @@
import android.content.Context;
import android.os.Parcel;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to show early warning if battery couldn't make to usual charging time
@@ -76,6 +78,12 @@
}
@Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_EARLY_WARNING_TIP,
+ mState);
+ }
+
+ @Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeBoolean(mPowerSaveModeOn);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTip.java
index 475ea56..3ce7538 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTip.java
@@ -21,9 +21,11 @@
import android.os.Parcelable;
import android.support.annotation.VisibleForTesting;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.utils.StringUtil;
import java.util.List;
@@ -78,6 +80,18 @@
mState = tip.mState;
}
+ @Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_HIGH_USAGE_TIP,
+ mState);
+ for (int i = 0, size = mHighUsageAppList.size(); i < size; i++) {
+ final AppInfo appInfo = mHighUsageAppList.get(i);
+ metricsFeatureProvider.action(context,
+ MetricsProto.MetricsEvent.ACTION_HIGH_USAGE_TIP_LIST,
+ appInfo.packageName);
+ }
+ }
+
public long getScreenTimeMs() {
return mScreenTimeMs;
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java
index 32cbe02..86237dd 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java
@@ -20,7 +20,9 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to show current battery life is short
@@ -55,6 +57,12 @@
mState = tip.mState;
}
+ @Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_LOW_BATTERY_TIP,
+ mState);
+ }
+
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new LowBatteryTip(in);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
index 037457a..566cbfa 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
@@ -19,11 +19,14 @@
import android.content.Context;
import android.content.res.Resources;
import android.os.Parcel;
+import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import java.util.ArrayList;
import java.util.List;
@@ -93,6 +96,24 @@
}
}
+ @Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP,
+ mState);
+ if (mState == StateType.NEW) {
+ for (int i = 0, size = mRestrictAppList.size(); i < size; i++) {
+ final AppInfo appInfo = mRestrictAppList.get(i);
+ for (Integer anomalyType : appInfo.anomalyTypes) {
+ metricsFeatureProvider.action(context,
+ MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP_LIST,
+ appInfo.packageName,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, anomalyType));
+ }
+
+ }
+ }
+ }
+
public List<AppInfo> getRestrictAppList() {
return mRestrictAppList;
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTip.java
index 7b408bb..68c7d70 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTip.java
@@ -20,7 +20,9 @@
import android.os.Parcel;
import android.provider.Settings;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to suggest turn on smart battery if it is not on
@@ -55,6 +57,12 @@
mState = tip.mState;
}
+ @Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_SMART_BATTERY_TIP,
+ mState);
+ }
+
public static final Creator CREATOR = new Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new SmartBatteryTip(in);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java
index 458bd2e..8993754 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java
@@ -20,7 +20,9 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to show general summary about battery life
@@ -55,6 +57,12 @@
mState = tip.mState;
}
+ @Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_SUMMARY_TIP,
+ mState);
+ }
+
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new SummaryTip(in);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/UnrestrictAppTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/UnrestrictAppTip.java
index ec67f6a..93de9b7 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/UnrestrictAppTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/UnrestrictAppTip.java
@@ -21,6 +21,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Tip to suggest user to remove app restriction. This is the empty tip and it is only used in
@@ -67,6 +68,11 @@
}
@Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ // Do nothing
+ }
+
+ @Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeParcelable(mAppInfo, flags);
diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java b/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java
index 80d3531..4c9715c 100644
--- a/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java
+++ b/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java
@@ -16,43 +16,31 @@
package com.android.settings.inputmethod;
-import android.annotation.Nullable;
-import android.app.Activity;
+import android.content.Context;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.input.InputManager.InputDeviceListener;
import android.hardware.input.KeyboardLayout;
import android.os.Bundle;
+import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.view.InputDevice;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSubtype;
-import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.Preconditions;
-import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.inputmethod.PhysicalKeyboardFragment.KeyboardInfoPreference;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
-public final class KeyboardLayoutPickerFragment extends SettingsPreferenceFragment
+public class KeyboardLayoutPickerFragment extends SettingsPreferenceFragment
implements InputDeviceListener {
-
private InputDeviceIdentifier mInputDeviceIdentifier;
private int mInputDeviceId = -1;
private InputManager mIm;
- private InputMethodInfo mImi;
- @Nullable
- private InputMethodSubtype mSubtype;
private KeyboardLayout[] mKeyboardLayouts;
- private Map<Preference, KeyboardLayout> mPreferenceMap = new HashMap<>();
-
- // TODO: Make these constants public API for b/25752827
+ private HashMap<CheckBoxPreference, KeyboardLayout> mPreferenceMap = new HashMap<>();
/**
* Intent extra: The input device descriptor of the keyboard whose keyboard
@@ -60,16 +48,6 @@
*/
public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
- /**
- * Intent extra: The associated {@link InputMethodInfo}.
- */
- public static final String EXTRA_INPUT_METHOD_INFO = "input_method_info";
-
- /**
- * Intent extra: The associated {@link InputMethodSubtype}.
- */
- public static final String EXTRA_INPUT_METHOD_SUBTYPE = "input_method_subtype";
-
@Override
public int getMetricsCategory() {
return MetricsEvent.INPUTMETHOD_KEYBOARD;
@@ -78,18 +56,14 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- Activity activity = Preconditions.checkNotNull(getActivity());
- mInputDeviceIdentifier = activity.getIntent().getParcelableExtra(
+ mInputDeviceIdentifier = getActivity().getIntent().getParcelableExtra(
EXTRA_INPUT_DEVICE_IDENTIFIER);
- mImi = activity.getIntent().getParcelableExtra(EXTRA_INPUT_METHOD_INFO);
- mSubtype = activity.getIntent().getParcelableExtra(EXTRA_INPUT_METHOD_SUBTYPE);
-
- if (mInputDeviceIdentifier == null || mImi == null) {
- activity.finish();
+ if (mInputDeviceIdentifier == null) {
+ getActivity().finish();
}
- mIm = activity.getSystemService(InputManager.class);
+ mIm = (InputManager) getSystemService(Context.INPUT_SERVICE);
mKeyboardLayouts = mIm.getKeyboardLayoutsForInputDevice(mInputDeviceIdentifier);
Arrays.sort(mKeyboardLayouts);
setPreferenceScreen(createPreferenceHierarchy());
@@ -108,6 +82,8 @@
return;
}
mInputDeviceId = inputDevice.getId();
+
+ updateCheckedState();
}
@Override
@@ -120,21 +96,34 @@
@Override
public boolean onPreferenceTreeClick(Preference preference) {
- KeyboardLayout layout = mPreferenceMap.get(preference);
- if (layout != null) {
- mIm.setKeyboardLayoutForInputDevice(mInputDeviceIdentifier, mImi, mSubtype,
- layout.getDescriptor());
- getActivity().finish();
- return true;
+ if (preference instanceof CheckBoxPreference) {
+ CheckBoxPreference checkboxPref = (CheckBoxPreference)preference;
+ KeyboardLayout layout = mPreferenceMap.get(checkboxPref);
+ if (layout != null) {
+ boolean checked = checkboxPref.isChecked();
+ if (checked) {
+ mIm.addKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
+ layout.getDescriptor());
+ } else {
+ mIm.removeKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
+ layout.getDescriptor());
+ }
+ return true;
+ }
}
return super.onPreferenceTreeClick(preference);
}
@Override
- public void onInputDeviceAdded(int deviceId) {}
+ public void onInputDeviceAdded(int deviceId) {
+ }
@Override
- public void onInputDeviceChanged(int deviceId) {}
+ public void onInputDeviceChanged(int deviceId) {
+ if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
+ updateCheckedState();
+ }
+ }
@Override
public void onInputDeviceRemoved(int deviceId) {
@@ -147,14 +136,23 @@
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
for (KeyboardLayout layout : mKeyboardLayouts) {
- Preference pref = new Preference(getPrefContext());
+ CheckBoxPreference pref = new CheckBoxPreference(getPrefContext());
pref.setTitle(layout.getLabel());
pref.setSummary(layout.getCollection());
root.addPreference(pref);
mPreferenceMap.put(pref, layout);
}
-
- root.setTitle(KeyboardInfoPreference.getDisplayName(getContext(), mImi, mSubtype));
return root;
}
+
+ private void updateCheckedState() {
+ String[] enabledKeyboardLayouts = mIm.getEnabledKeyboardLayoutsForInputDevice(
+ mInputDeviceIdentifier);
+ Arrays.sort(enabledKeyboardLayouts);
+
+ for (Map.Entry<CheckBoxPreference, KeyboardLayout> entry : mPreferenceMap.entrySet()) {
+ entry.getKey().setChecked(Arrays.binarySearch(enabledKeyboardLayouts,
+ entry.getValue().getDescriptor()) >= 0);
+ }
+ }
}
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
index 83d501d..a02a6d0 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
@@ -19,11 +19,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
-import android.app.LoaderManager;
-import android.content.AsyncTaskLoader;
import android.content.Context;
import android.content.Intent;
-import android.content.Loader;
import android.database.ContentObserver;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
@@ -40,9 +37,6 @@
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import android.view.InputDevice;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.inputmethod.InputMethodUtils;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -52,33 +46,25 @@
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
-import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
+import com.android.settingslib.utils.ThreadUtils;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Objects;
public final class PhysicalKeyboardFragment extends SettingsPreferenceFragment
- implements InputManager.InputDeviceListener, Indexable {
+ implements InputManager.InputDeviceListener,
+ KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener, Indexable {
private static final String KEYBOARD_ASSISTANCE_CATEGORY = "keyboard_assistance_category";
private static final String SHOW_VIRTUAL_KEYBOARD_SWITCH = "show_virtual_keyboard_switch";
private static final String KEYBOARD_SHORTCUTS_HELPER = "keyboard_shortcuts_helper";
- private static final String IM_SUBTYPE_MODE_KEYBOARD = "keyboard";
@NonNull
- private final List<HardKeyboardDeviceInfo> mLastHardKeyboards = new ArrayList<>();
- @NonNull
- private final List<KeyboardInfoPreference> mTempKeyboardInfoList = new ArrayList<>();
-
- @NonNull
- private final HashSet<Integer> mLoaderIDs = new HashSet<>();
- private int mNextLoaderId = 0;
+ private final ArrayList<HardKeyboardDeviceInfo> mLastHardKeyboards = new ArrayList<>();
private InputManager mIm;
@NonNull
@@ -88,6 +74,8 @@
@NonNull
private InputMethodUtils.InputMethodSettings mSettings;
+ private Intent mIntentWaitingForResult;
+
@Override
public void onCreatePreferences(Bundle bundle, String s) {
Activity activity = Preconditions.checkNotNull(getActivity());
@@ -118,9 +106,8 @@
@Override
public void onResume() {
super.onResume();
- clearLoader();
mLastHardKeyboards.clear();
- updateHardKeyboards();
+ scheduleUpdateHardKeyboards();
mIm.registerInputDeviceListener(this, null);
mShowVirtualKeyboardSwitch.setOnPreferenceChangeListener(
mShowVirtualKeyboardSwitchPreferenceChangeListener);
@@ -130,67 +117,25 @@
@Override
public void onPause() {
super.onPause();
- clearLoader();
mLastHardKeyboards.clear();
mIm.unregisterInputDeviceListener(this);
mShowVirtualKeyboardSwitch.setOnPreferenceChangeListener(null);
unregisterShowVirtualKeyboardSettingsObserver();
}
- private void onLoadFinishedInternal(
- final int loaderId, @NonNull final List<Keyboards> keyboardsList) {
- if (!mLoaderIDs.remove(loaderId)) {
- // Already destroyed loader. Ignore.
- return;
- }
-
- Collections.sort(keyboardsList);
- final PreferenceScreen preferenceScreen = getPreferenceScreen();
- preferenceScreen.removeAll();
- for (Keyboards keyboards : keyboardsList) {
- final PreferenceCategory category = new PreferenceCategory(getPrefContext(), null);
- category.setTitle(keyboards.mDeviceInfo.mDeviceName);
- category.setOrder(0);
- preferenceScreen.addPreference(category);
- for (Keyboards.KeyboardInfo info : keyboards.mKeyboardInfoList) {
- mTempKeyboardInfoList.clear();
- final InputMethodInfo imi = info.mImi;
- final InputMethodSubtype imSubtype = info.mImSubtype;
- if (imi != null) {
- KeyboardInfoPreference pref =
- new KeyboardInfoPreference(getPrefContext(), info);
- pref.setOnPreferenceClickListener(preference -> {
- showKeyboardLayoutScreen(
- keyboards.mDeviceInfo.mDeviceIdentifier, imi, imSubtype);
- return true;
- });
- mTempKeyboardInfoList.add(pref);
- Collections.sort(mTempKeyboardInfoList);
- }
- for (KeyboardInfoPreference pref : mTempKeyboardInfoList) {
- category.addPreference(pref);
- }
- }
- }
- mTempKeyboardInfoList.clear();
- mKeyboardAssistanceCategory.setOrder(1);
- preferenceScreen.addPreference(mKeyboardAssistanceCategory);
- updateShowVirtualKeyboardSwitch();
- }
-
@Override
public void onInputDeviceAdded(int deviceId) {
- updateHardKeyboards();
+ scheduleUpdateHardKeyboards();
}
@Override
public void onInputDeviceRemoved(int deviceId) {
- updateHardKeyboards();
+ scheduleUpdateHardKeyboards();
}
@Override
public void onInputDeviceChanged(int deviceId) {
- updateHardKeyboards();
+ scheduleUpdateHardKeyboards();
}
@Override
@@ -198,50 +143,57 @@
return MetricsEvent.PHYSICAL_KEYBOARDS;
}
- @NonNull
- public static List<HardKeyboardDeviceInfo> getHardKeyboards() {
- final List<HardKeyboardDeviceInfo> keyboards = new ArrayList<>();
- final int[] devicesIds = InputDevice.getDeviceIds();
- for (int deviceId : devicesIds) {
- final InputDevice device = InputDevice.getDevice(deviceId);
- if (device != null && !device.isVirtual() && device.isFullKeyboard()) {
- keyboards.add(new HardKeyboardDeviceInfo(device.getName(), device.getIdentifier()));
- }
- }
- return keyboards;
+ private void scheduleUpdateHardKeyboards() {
+ final Context context = getContext();
+ ThreadUtils.postOnBackgroundThread(() -> {
+ final List<HardKeyboardDeviceInfo> newHardKeyboards = getHardKeyboards(context);
+ ThreadUtils.postOnMainThread(() -> updateHardKeyboards(newHardKeyboards));
+ });
}
- private void updateHardKeyboards() {
- final List<HardKeyboardDeviceInfo> newHardKeyboards = getHardKeyboards();
- if (!Objects.equals(newHardKeyboards, mLastHardKeyboards)) {
- clearLoader();
- mLastHardKeyboards.clear();
- mLastHardKeyboards.addAll(newHardKeyboards);
- mLoaderIDs.add(mNextLoaderId);
- getLoaderManager().initLoader(mNextLoaderId, null,
- new Callbacks(getContext(), this, mLastHardKeyboards));
- ++mNextLoaderId;
+ private void updateHardKeyboards(@NonNull List<HardKeyboardDeviceInfo> newHardKeyboards) {
+ if (Objects.equals(mLastHardKeyboards, newHardKeyboards)) {
+ // Nothing has changed. Ignore.
+ return;
}
+
+ // TODO(yukawa): Maybe we should follow the style used in ConnectedDeviceDashboardFragment.
+
+ mLastHardKeyboards.clear();
+ mLastHardKeyboards.addAll(newHardKeyboards);
+
+ final PreferenceScreen preferenceScreen = getPreferenceScreen();
+ preferenceScreen.removeAll();
+ final PreferenceCategory category = new PreferenceCategory(getPrefContext());
+ category.setTitle(R.string.builtin_keyboard_settings_title);
+ category.setOrder(0);
+ preferenceScreen.addPreference(category);
+
+ for (HardKeyboardDeviceInfo hardKeyboardDeviceInfo : newHardKeyboards) {
+ // TODO(yukawa): Consider using com.android.settings.widget.GearPreference
+ final Preference pref = new Preference(getPrefContext());
+ pref.setTitle(hardKeyboardDeviceInfo.mDeviceName);
+ pref.setSummary(hardKeyboardDeviceInfo.mLayoutLabel);
+ pref.setOnPreferenceClickListener(preference -> {
+ showKeyboardLayoutDialog(hardKeyboardDeviceInfo.mDeviceIdentifier);
+ return true;
+ });
+ category.addPreference(pref);
+ }
+
+ mKeyboardAssistanceCategory.setOrder(1);
+ preferenceScreen.addPreference(mKeyboardAssistanceCategory);
+ updateShowVirtualKeyboardSwitch();
}
- private void showKeyboardLayoutScreen(
- @NonNull InputDeviceIdentifier inputDeviceIdentifier,
- @NonNull InputMethodInfo imi,
- @Nullable InputMethodSubtype imSubtype) {
- final Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClass(getActivity(), Settings.KeyboardLayoutPickerActivity.class);
- intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
- inputDeviceIdentifier);
- intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_METHOD_INFO, imi);
- intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_METHOD_SUBTYPE, imSubtype);
- startActivity(intent);
- }
-
- private void clearLoader() {
- for (final int loaderId : mLoaderIDs) {
- getLoaderManager().destroyLoader(loaderId);
+ private void showKeyboardLayoutDialog(InputDeviceIdentifier inputDeviceIdentifier) {
+ KeyboardLayoutDialogFragment fragment = (KeyboardLayoutDialogFragment)
+ getFragmentManager().findFragmentByTag("keyboardLayout");
+ if (fragment == null) {
+ fragment = new KeyboardLayoutDialogFragment(inputDeviceIdentifier);
+ fragment.setTargetFragment(this, 0);
+ fragment.show(getActivity().getFragmentManager(), "keyboardLayout");
}
- mLoaderIDs.clear();
}
private void registerShowVirtualKeyboardSettingsObserver() {
@@ -282,102 +234,75 @@
}
};
- private static final class Callbacks implements LoaderManager.LoaderCallbacks<List<Keyboards>> {
- @NonNull
- final Context mContext;
- @NonNull
- final PhysicalKeyboardFragment mPhysicalKeyboardFragment;
- @NonNull
- final List<HardKeyboardDeviceInfo> mHardKeyboards;
+ @Override
+ public void onSetupKeyboardLayouts(InputDeviceIdentifier inputDeviceIdentifier) {
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClass(getActivity(), Settings.KeyboardLayoutPickerActivity.class);
+ intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
+ inputDeviceIdentifier);
+ mIntentWaitingForResult = intent;
+ startActivityForResult(intent, 0);
+ }
- public Callbacks(
- @NonNull Context context,
- @NonNull PhysicalKeyboardFragment physicalKeyboardFragment,
- @NonNull List<HardKeyboardDeviceInfo> hardKeyboards) {
- mContext = context;
- mPhysicalKeyboardFragment = physicalKeyboardFragment;
- mHardKeyboards = hardKeyboards;
- }
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
- @Override
- public Loader<List<Keyboards>> onCreateLoader(int id, Bundle args) {
- return new KeyboardLayoutLoader(mContext, mHardKeyboards);
- }
-
- @Override
- public void onLoadFinished(Loader<List<Keyboards>> loader, List<Keyboards> data) {
- mPhysicalKeyboardFragment.onLoadFinishedInternal(loader.getId(), data);
- }
-
- @Override
- public void onLoaderReset(Loader<List<Keyboards>> loader) {
+ if (mIntentWaitingForResult != null) {
+ InputDeviceIdentifier inputDeviceIdentifier = mIntentWaitingForResult
+ .getParcelableExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER);
+ mIntentWaitingForResult = null;
+ showKeyboardLayoutDialog(inputDeviceIdentifier);
}
}
- private static final class KeyboardLayoutLoader extends AsyncTaskLoader<List<Keyboards>> {
- @NonNull
- private final List<HardKeyboardDeviceInfo> mHardKeyboards;
-
- public KeyboardLayoutLoader(
- @NonNull Context context,
- @NonNull List<HardKeyboardDeviceInfo> hardKeyboards) {
- super(context);
- mHardKeyboards = Preconditions.checkNotNull(hardKeyboards);
+ private static String getLayoutLabel(@NonNull InputDevice device,
+ @NonNull Context context, @NonNull InputManager im) {
+ final String currentLayoutDesc =
+ im.getCurrentKeyboardLayoutForInputDevice(device.getIdentifier());
+ if (currentLayoutDesc == null) {
+ return context.getString(R.string.keyboard_layout_default_label);
}
+ final KeyboardLayout currentLayout = im.getKeyboardLayout(currentLayoutDesc);
+ if (currentLayout == null) {
+ return context.getString(R.string.keyboard_layout_default_label);
+ }
+ // If current layout is specified but the layout is null, just return an empty string
+ // instead of falling back to R.string.keyboard_layout_default_label.
+ return TextUtils.emptyIfNull(currentLayout.getLabel());
+ }
- private Keyboards loadInBackground(HardKeyboardDeviceInfo deviceInfo) {
- final ArrayList<Keyboards.KeyboardInfo> keyboardInfoList = new ArrayList<>();
- final InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
- final InputManager im = getContext().getSystemService(InputManager.class);
- if (imm != null && im != null) {
- for (InputMethodInfo imi : imm.getEnabledInputMethodList()) {
- final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(
- imi, true /* allowsImplicitlySelectedSubtypes */);
- if (subtypes.isEmpty()) {
- // Here we use null to indicate that this IME has no subtype.
- final InputMethodSubtype nullSubtype = null;
- final KeyboardLayout layout = im.getKeyboardLayoutForInputDevice(
- deviceInfo.mDeviceIdentifier, imi, nullSubtype);
- keyboardInfoList.add(new Keyboards.KeyboardInfo(imi, nullSubtype, layout));
- continue;
- }
-
- // If the IME supports subtypes, we pick up "keyboard" subtypes only.
- final int N = subtypes.size();
- for (int i = 0; i < N; ++i) {
- final InputMethodSubtype subtype = subtypes.get(i);
- if (!IM_SUBTYPE_MODE_KEYBOARD.equalsIgnoreCase(subtype.getMode())) {
- continue;
- }
- final KeyboardLayout layout = im.getKeyboardLayoutForInputDevice(
- deviceInfo.mDeviceIdentifier, imi, subtype);
- keyboardInfoList.add(new Keyboards.KeyboardInfo(imi, subtype, layout));
- }
- }
+ @NonNull
+ static List<HardKeyboardDeviceInfo> getHardKeyboards(@NonNull Context context) {
+ final List<HardKeyboardDeviceInfo> keyboards = new ArrayList<>();
+ final InputManager im = context.getSystemService(InputManager.class);
+ if (im == null) {
+ return new ArrayList<>();
+ }
+ for (int deviceId : InputDevice.getDeviceIds()) {
+ final InputDevice device = InputDevice.getDevice(deviceId);
+ if (device == null || device.isVirtual() || !device.isFullKeyboard()) {
+ continue;
}
- return new Keyboards(deviceInfo, keyboardInfoList);
+ keyboards.add(new HardKeyboardDeviceInfo(
+ device.getName(), device.getIdentifier(), getLayoutLabel(device, context, im)));
}
- @Override
- public List<Keyboards> loadInBackground() {
- List<Keyboards> keyboardsList = new ArrayList<>(mHardKeyboards.size());
- for (HardKeyboardDeviceInfo deviceInfo : mHardKeyboards) {
- keyboardsList.add(loadInBackground(deviceInfo));
+ // We intentionally don't reuse Comparator because Collator may not be thread-safe.
+ final Collator collator = Collator.getInstance();
+ keyboards.sort((a, b) -> {
+ int result = collator.compare(a.mDeviceName, b.mDeviceName);
+ if (result != 0) {
+ return result;
}
- return keyboardsList;
- }
-
- @Override
- protected void onStartLoading() {
- super.onStartLoading();
- forceLoad();
- }
-
- @Override
- protected void onStopLoading() {
- super.onStopLoading();
- cancelLoad();
- }
+ result = a.mDeviceIdentifier.getDescriptor().compareTo(
+ b.mDeviceIdentifier.getDescriptor());
+ if (result != 0) {
+ return result;
+ }
+ return collator.compare(a.mLayoutLabel, b.mLayoutLabel);
+ });
+ return keyboards;
}
public static final class HardKeyboardDeviceInfo {
@@ -385,12 +310,16 @@
public final String mDeviceName;
@NonNull
public final InputDeviceIdentifier mDeviceIdentifier;
+ @NonNull
+ public final String mLayoutLabel;
public HardKeyboardDeviceInfo(
- @Nullable final String deviceName,
- @NonNull final InputDeviceIdentifier deviceIdentifier) {
- mDeviceName = deviceName != null ? deviceName : "";
+ @Nullable String deviceName,
+ @NonNull InputDeviceIdentifier deviceIdentifier,
+ @NonNull String layoutLabel) {
+ mDeviceName = TextUtils.emptyIfNull(deviceName);
mDeviceIdentifier = deviceIdentifier;
+ mLayoutLabel = layoutLabel;
}
@Override
@@ -404,14 +333,10 @@
if (!TextUtils.equals(mDeviceName, that.mDeviceName)) {
return false;
}
- if (mDeviceIdentifier.getVendorId() != that.mDeviceIdentifier.getVendorId()) {
+ if (!Objects.equals(mDeviceIdentifier, that.mDeviceIdentifier)) {
return false;
}
- if (mDeviceIdentifier.getProductId() != that.mDeviceIdentifier.getProductId()) {
- return false;
- }
- if (!TextUtils.equals(mDeviceIdentifier.getDescriptor(),
- that.mDeviceIdentifier.getDescriptor())) {
+ if (!TextUtils.equals(mLayoutLabel, that.mLayoutLabel)) {
return false;
}
@@ -419,121 +344,6 @@
}
}
- public static final class Keyboards implements Comparable<Keyboards> {
- @NonNull
- public final HardKeyboardDeviceInfo mDeviceInfo;
- @NonNull
- public final ArrayList<KeyboardInfo> mKeyboardInfoList;
- @NonNull
- public final Collator mCollator = Collator.getInstance();
-
- public Keyboards(
- @NonNull final HardKeyboardDeviceInfo deviceInfo,
- @NonNull final ArrayList<KeyboardInfo> keyboardInfoList) {
- mDeviceInfo = deviceInfo;
- mKeyboardInfoList = keyboardInfoList;
- }
-
- @Override
- public int compareTo(@NonNull Keyboards another) {
- return mCollator.compare(mDeviceInfo.mDeviceName, another.mDeviceInfo.mDeviceName);
- }
-
- public static final class KeyboardInfo {
- @NonNull
- public final InputMethodInfo mImi;
- @Nullable
- public final InputMethodSubtype mImSubtype;
- @NonNull
- public final KeyboardLayout mLayout;
-
- public KeyboardInfo(
- @NonNull final InputMethodInfo imi,
- @Nullable final InputMethodSubtype imSubtype,
- @NonNull final KeyboardLayout layout) {
- mImi = imi;
- mImSubtype = imSubtype;
- mLayout = layout;
- }
- }
- }
-
- static final class KeyboardInfoPreference extends Preference {
-
- @NonNull
- private final CharSequence mImeName;
- @Nullable
- private final CharSequence mImSubtypeName;
- @NonNull
- private final Collator collator = Collator.getInstance();
-
- private KeyboardInfoPreference(
- @NonNull Context context, @NonNull Keyboards.KeyboardInfo info) {
- super(context);
- mImeName = info.mImi.loadLabel(context.getPackageManager());
- mImSubtypeName = getImSubtypeName(context, info.mImi, info.mImSubtype);
- setTitle(formatDisplayName(context, mImeName, mImSubtypeName));
- if (info.mLayout != null) {
- setSummary(info.mLayout.getLabel());
- }
- }
-
- @NonNull
- static CharSequence getDisplayName(
- @NonNull Context context, @NonNull InputMethodInfo imi,
- @Nullable InputMethodSubtype imSubtype) {
- final CharSequence imeName = imi.loadLabel(context.getPackageManager());
- final CharSequence imSubtypeName = getImSubtypeName(context, imi, imSubtype);
- return formatDisplayName(context, imeName, imSubtypeName);
- }
-
- private static CharSequence formatDisplayName(
- @NonNull Context context,
- @NonNull CharSequence imeName, @Nullable CharSequence imSubtypeName) {
- if (imSubtypeName == null) {
- return imeName;
- }
- return String.format(
- context.getString(R.string.physical_device_title), imeName, imSubtypeName);
- }
-
- @Nullable
- private static CharSequence getImSubtypeName(
- @NonNull Context context, @NonNull InputMethodInfo imi,
- @Nullable InputMethodSubtype imSubtype) {
- if (imSubtype != null) {
- return InputMethodAndSubtypeUtil.getSubtypeLocaleNameAsSentence(
- imSubtype, context, imi);
- }
- return null;
- }
-
- @Override
- public int compareTo(@NonNull Preference object) {
- if (!(object instanceof KeyboardInfoPreference)) {
- return super.compareTo(object);
- }
- KeyboardInfoPreference another = (KeyboardInfoPreference) object;
- int result = compare(mImeName, another.mImeName);
- if (result == 0) {
- result = compare(mImSubtypeName, another.mImSubtypeName);
- }
- return result;
- }
-
- private int compare(@Nullable CharSequence lhs, @Nullable CharSequence rhs) {
- if (!TextUtils.isEmpty(lhs) && !TextUtils.isEmpty(rhs)) {
- return collator.compare(lhs.toString(), rhs.toString());
- } else if (TextUtils.isEmpty(lhs) && TextUtils.isEmpty(rhs)) {
- return 0;
- } else if (!TextUtils.isEmpty(lhs)) {
- return -1;
- } else {
- return 1;
- }
- }
- }
-
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java b/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java
index f80b68f..b9e95be 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceController.java
@@ -94,7 +94,7 @@
return;
}
final List<HardKeyboardDeviceInfo> keyboards =
- PhysicalKeyboardFragment.getHardKeyboards();
+ PhysicalKeyboardFragment.getHardKeyboards(mContext);
if (keyboards.isEmpty()) {
mPreference.setSummary(R.string.disconnected);
return;
diff --git a/src/com/android/settings/notification/AbstractZenModePreferenceController.java b/src/com/android/settings/notification/AbstractZenModePreferenceController.java
index 9180791..c60299e 100644
--- a/src/com/android/settings/notification/AbstractZenModePreferenceController.java
+++ b/src/com/android/settings/notification/AbstractZenModePreferenceController.java
@@ -112,10 +112,17 @@
mBackend.mZenMode);
}
+ protected int getZenDuration() {
+ return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ZEN_DURATION,
+ 0);
+ }
+
class SettingObserver extends ContentObserver {
private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor(
Settings.Global.ZEN_MODE_CONFIG_ETAG);
+ private final Uri ZEN_MODE_DURATION_URI = Settings.Global.getUriFor(
+ Settings.Global.ZEN_DURATION);
private final Preference mPreference;
@@ -127,6 +134,7 @@
public void register(ContentResolver cr) {
cr.registerContentObserver(ZEN_MODE_URI, false, this, UserHandle.USER_ALL);
cr.registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false, this, UserHandle.USER_ALL);
+ cr.registerContentObserver(ZEN_MODE_DURATION_URI, false, this, UserHandle.USER_ALL);
}
public void unregister(ContentResolver cr) {
@@ -136,11 +144,8 @@
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
- if (ZEN_MODE_URI.equals(uri)) {
- updateState(mPreference);
- }
-
- if (ZEN_MODE_CONFIG_ETAG_URI.equals(uri)) {
+ if (ZEN_MODE_URI.equals(uri) || ZEN_MODE_CONFIG_ETAG_URI.equals(uri)
+ || ZEN_MODE_DURATION_URI.equals(uri)) {
updateState(mPreference);
}
}
diff --git a/src/com/android/settings/notification/SettingsZenDurationDialog.java b/src/com/android/settings/notification/SettingsZenDurationDialog.java
new file mode 100644
index 0000000..23bf1a9
--- /dev/null
+++ b/src/com/android/settings/notification/SettingsZenDurationDialog.java
@@ -0,0 +1,37 @@
+/*
+ * 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.notification;
+
+import android.app.Dialog;
+import android.os.Bundle;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+public class SettingsZenDurationDialog extends InstrumentedDialogFragment {
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new com.android.settingslib.notification.ZenDurationDialog(
+ getContext()).createDialog();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.NOTIFICATION_ZEN_MODE_DURATION_DIALOG;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenModeAutomationPreferenceController.java b/src/com/android/settings/notification/ZenModeAutomationPreferenceController.java
index aa46d4e..792a272 100644
--- a/src/com/android/settings/notification/ZenModeAutomationPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeAutomationPreferenceController.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.android.settings.notification;
import android.content.Context;
diff --git a/src/com/android/settings/notification/ZenModeBackend.java b/src/com/android/settings/notification/ZenModeBackend.java
index e8f103e..3c6a026 100644
--- a/src/com/android/settings/notification/ZenModeBackend.java
+++ b/src/com/android/settings/notification/ZenModeBackend.java
@@ -16,9 +16,11 @@
package com.android.settings.notification;
+import android.app.ActivityManager;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.content.Context;
+import android.net.Uri;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import android.support.annotation.VisibleForTesting;
@@ -79,7 +81,15 @@
protected void setZenMode(int zenMode) {
NotificationManager.from(mContext).setZenMode(zenMode, null, TAG);
- mZenMode = zenMode;
+ mZenMode = getZenMode();
+ }
+
+ protected void setZenModeForDuration(int minutes) {
+ Uri conditionId = ZenModeConfig.toTimeCondition(mContext, minutes,
+ ActivityManager.getCurrentUser(), true).id;
+ mNotificationManager.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ conditionId, TAG);
+ mZenMode = getZenMode();
}
protected int getZenMode() {
@@ -88,6 +98,10 @@
return mZenMode;
}
+ protected boolean isVisualEffectSuppressed(int visualEffect) {
+ return (mPolicy.suppressedVisualEffects & visualEffect) != 0;
+ }
+
protected boolean isPriorityCategoryEnabled(int categoryType) {
return (mPolicy.priorityCategories & categoryType) != 0;
}
@@ -117,8 +131,8 @@
return SOURCE_NONE;
}
- protected void saveVisualEffectsPolicy(int category, boolean canBypass) {
- int suppressedEffects = getNewSuppressedEffects(!canBypass, category);
+ protected void saveVisualEffectsPolicy(int category, boolean suppress) {
+ int suppressedEffects = getNewSuppressedEffects(suppress, category);
savePolicy(mPolicy.priorityCategories, mPolicy.priorityCallSenders,
mPolicy.priorityMessageSenders, suppressedEffects);
}
diff --git a/src/com/android/settings/notification/ZenModeBehaviorPreferenceController.java b/src/com/android/settings/notification/ZenModeBehaviorPreferenceController.java
index 0e1f066..cf6218c 100644
--- a/src/com/android/settings/notification/ZenModeBehaviorPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeBehaviorPreferenceController.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.android.settings.notification;
import android.content.Context;
diff --git a/src/com/android/settings/notification/ZenModeBehaviorSettings.java b/src/com/android/settings/notification/ZenModeBehaviorSettings.java
index 7b5fa04..31542c3 100644
--- a/src/com/android/settings/notification/ZenModeBehaviorSettings.java
+++ b/src/com/android/settings/notification/ZenModeBehaviorSettings.java
@@ -49,8 +49,6 @@
controllers.add(new ZenModeRepeatCallersPreferenceController(context, lifecycle,
context.getResources().getInteger(com.android.internal.R.integer
.config_zen_repeat_callers_threshold)));
- controllers.add(new ZenModeScreenOnPreferenceController(context, lifecycle));
- controllers.add(new ZenModeScreenOffPreferenceController(context, lifecycle));
controllers.add(new ZenModeBehaviorFooterPreferenceController(context, lifecycle));
return controllers;
}
@@ -85,15 +83,6 @@
@Override
public List<String> getNonIndexableKeys(Context context) {
final List<String> keys = super.getNonIndexableKeys(context);
- keys.add(ZenModeAlarmsPreferenceController.KEY);
- keys.add(ZenModeMediaPreferenceController.KEY);
- keys.add(ZenModeEventsPreferenceController.KEY);
- keys.add(ZenModeRemindersPreferenceController.KEY);
- keys.add(ZenModeMessagesPreferenceController.KEY);
- keys.add(ZenModeCallsPreferenceController.KEY);
- keys.add(ZenModeRepeatCallersPreferenceController.KEY);
- keys.add(ZenModeScreenOnPreferenceController.KEY);
- keys.add(ZenModeScreenOffPreferenceController.KEY);
return keys;
}
diff --git a/src/com/android/settings/notification/ZenModeBlockedEffectsPreferenceController.java b/src/com/android/settings/notification/ZenModeBlockedEffectsPreferenceController.java
new file mode 100644
index 0000000..9500320
--- /dev/null
+++ b/src/com/android/settings/notification/ZenModeBlockedEffectsPreferenceController.java
@@ -0,0 +1,51 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenModeBlockedEffectsPreferenceController extends
+ AbstractZenModePreferenceController implements PreferenceControllerMixin {
+
+ protected static final String KEY = "zen_mode_block_effects_settings";
+ private final ZenModeSettings.SummaryBuilder mSummaryBuilder;
+
+ public ZenModeBlockedEffectsPreferenceController(Context context, Lifecycle lifecycle) {
+ super(context, KEY, lifecycle);
+ mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mSummaryBuilder.getBlockedEffectsSummary(getPolicy());
+ }
+
+}
diff --git a/src/com/android/settings/notification/ZenModeBlockedEffectsSettings.java b/src/com/android/settings/notification/ZenModeBlockedEffectsSettings.java
new file mode 100644
index 0000000..0cac9cb
--- /dev/null
+++ b/src/com/android/settings/notification/ZenModeBlockedEffectsSettings.java
@@ -0,0 +1,123 @@
+/*
+ * 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.notification;
+
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
+
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+import android.support.v7.preference.CheckBoxPreference;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenModeBlockedEffectsSettings extends ZenModeSettingsBase implements Indexable {
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ CheckBoxPreference soundPreference =
+ (CheckBoxPreference) getPreferenceScreen().findPreference("zen_effect_sound");
+ if (soundPreference != null) {
+ soundPreference.setChecked(true);
+ }
+ }
+
+ @Override
+ protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context, getLifecycle());
+ }
+
+ private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
+ Lifecycle lifecycle) {
+ List<AbstractPreferenceController> controllers = new ArrayList<>();
+ controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
+ "zen_effect_intent", SUPPRESSED_EFFECT_FULL_SCREEN_INTENT,
+ MetricsEvent.ACTION_ZEN_BLOCK_FULL_SCREEN_INTENTS, null));
+ controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
+ "zen_effect_light", SUPPRESSED_EFFECT_LIGHTS,
+ MetricsEvent.ACTION_ZEN_BLOCK_LIGHT, null));
+ controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
+ "zen_effect_peek", SUPPRESSED_EFFECT_PEEK,
+ MetricsEvent.ACTION_ZEN_BLOCK_PEEK, null));
+ controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
+ "zen_effect_status", SUPPRESSED_EFFECT_STATUS_BAR,
+ MetricsEvent.ACTION_ZEN_BLOCK_STATUS,
+ new int[] {SUPPRESSED_EFFECT_NOTIFICATION_LIST}));
+ controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
+ "zen_effect_badge", SUPPRESSED_EFFECT_BADGE,
+ MetricsEvent.ACTION_ZEN_BLOCK_BADGE, null));
+ controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
+ "zen_effect_ambient", SUPPRESSED_EFFECT_AMBIENT,
+ MetricsEvent.ACTION_ZEN_BLOCK_AMBIENT, null));
+ controllers.add(new ZenModeVisEffectPreferenceController(context, lifecycle,
+ "zen_effect_list", SUPPRESSED_EFFECT_NOTIFICATION_LIST,
+ MetricsEvent.ACTION_ZEN_BLOCK_NOTIFICATION_LIST, null));
+ return controllers;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.zen_mode_block_settings;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.ZEN_WHAT_TO_BLOCK;
+ }
+
+ /**
+ * For Search.
+ */
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ final ArrayList<SearchIndexableResource> result = new ArrayList<>();
+
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.zen_mode_block_settings;
+ result.add(sir);
+ return result;
+ }
+
+ @Override
+ public List<String> getNonIndexableKeys(Context context) {
+ final List<String> keys = super.getNonIndexableKeys(context);
+ return keys;
+ }
+
+ @Override
+ public List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context, null);
+ }
+ };
+}
diff --git a/src/com/android/settings/notification/ZenModeButtonPreferenceController.java b/src/com/android/settings/notification/ZenModeButtonPreferenceController.java
index d9c9691..12008a1 100644
--- a/src/com/android/settings/notification/ZenModeButtonPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeButtonPreferenceController.java
@@ -61,8 +61,7 @@
if (null == mZenButtonOn) {
mZenButtonOn = (Button) ((LayoutPreference) preference)
.findViewById(R.id.zen_mode_settings_turn_on_button);
- mZenButtonOn.setOnClickListener(v ->
- new SettingsEnableZenModeDialog().show(mFragment, TAG));
+ updateZenButtonOnClickListener();
}
if (null == mZenButtonOff) {
@@ -89,7 +88,34 @@
case Settings.Global.ZEN_MODE_OFF:
default:
mZenButtonOff.setVisibility(View.GONE);
+ updateZenButtonOnClickListener();
mZenButtonOn.setVisibility(View.VISIBLE);
}
}
+
+ private void updateZenButtonOnClickListener() {
+ int zenDuration = getZenDuration();
+ switch (zenDuration) {
+ case Settings.Global.ZEN_DURATION_PROMPT:
+ mZenButtonOn.setOnClickListener(v -> {
+ mMetricsFeatureProvider.action(mContext,
+ MetricsProto.MetricsEvent.ACTION_ZEN_TOGGLE_DND_BUTTON, false);
+ new SettingsEnableZenModeDialog().show(mFragment, TAG);
+ });
+ break;
+ case Settings.Global.ZEN_DURATION_FOREVER:
+ mZenButtonOn.setOnClickListener(v -> {
+ mMetricsFeatureProvider.action(mContext,
+ MetricsProto.MetricsEvent.ACTION_ZEN_TOGGLE_DND_BUTTON, false);
+ mBackend.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ });
+ break;
+ default:
+ mZenButtonOn.setOnClickListener(v -> {
+ mMetricsFeatureProvider.action(mContext,
+ MetricsProto.MetricsEvent.ACTION_ZEN_TOGGLE_DND_BUTTON, false);
+ mBackend.setZenModeForDuration(zenDuration);
+ });
+ }
+ }
}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/ZenModeDurationPreferenceController.java b/src/com/android/settings/notification/ZenModeDurationPreferenceController.java
new file mode 100644
index 0000000..0cd0eb3
--- /dev/null
+++ b/src/com/android/settings/notification/ZenModeDurationPreferenceController.java
@@ -0,0 +1,86 @@
+/*
+ * 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.notification;
+
+import android.app.FragmentManager;
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenModeDurationPreferenceController extends AbstractZenModePreferenceController
+ implements PreferenceControllerMixin, Preference.OnPreferenceClickListener {
+
+ private static final String TAG = "ZenModeDurationDialog";
+ protected static final String KEY = "zen_mode_duration_settings";
+ private FragmentManager mFragment;
+
+ public ZenModeDurationPreferenceController(Context context, Lifecycle lifecycle, FragmentManager
+ fragment) {
+ super(context, KEY, lifecycle);
+ mFragment = fragment;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ screen.findPreference(KEY).setOnPreferenceClickListener(this);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+
+ String summary = "";
+ int zenDuration = getZenDuration();
+ if (zenDuration < 0) {
+ summary = mContext.getString(R.string.zen_mode_duration_summary_always_prompt);
+ } else if (zenDuration == 0) {
+ summary = mContext.getString(R.string.zen_mode_duration_summary_forever);
+ } else {
+ if (zenDuration >= 60) {
+ int hours = zenDuration / 60;
+ summary = mContext.getResources().getQuantityString(
+ R.plurals.zen_mode_duration_summary_time_hours, hours, hours);
+ } else {
+ summary = mContext.getResources().getString(
+ R.string.zen_mode_duration_summary_time_minutes, zenDuration);
+ }
+ }
+
+ preference.setSummary(summary);
+ }
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ new SettingsZenDurationDialog().show(mFragment, TAG);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/ZenModeScreenOffPreferenceController.java b/src/com/android/settings/notification/ZenModeScreenOffPreferenceController.java
deleted file mode 100644
index 81c9b0d..0000000
--- a/src/com/android/settings/notification/ZenModeScreenOffPreferenceController.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.notification;
-
-import android.app.NotificationManager.Policy;
-import android.content.Context;
-import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.Preference;
-import android.util.Log;
-
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-public class ZenModeScreenOffPreferenceController extends
- AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener {
-
- protected static final String KEY = "zen_mode_screen_off";
-
- public ZenModeScreenOffPreferenceController(Context context, Lifecycle lifecycle) {
- super(context, KEY, lifecycle);
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY;
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public void updateState(Preference preference) {
- super.updateState(preference);
-
- SwitchPreference pref = (SwitchPreference) preference;
- pref.setChecked(mBackend.isEffectAllowed(Policy.SUPPRESSED_EFFECT_SCREEN_OFF));
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final boolean bypass = (Boolean) newValue;
- if (ZenModeSettingsBase.DEBUG) {
- Log.d(TAG, "onPrefChange allowWhenScreenOff=" + bypass);
- }
- mMetricsFeatureProvider.action(mContext,
- MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_WHEN_SCREEN_OFF, bypass);
- mBackend.saveVisualEffectsPolicy(Policy.SUPPRESSED_EFFECT_SCREEN_OFF, bypass);
- return true;
- }
-}
diff --git a/src/com/android/settings/notification/ZenModeScreenOnPreferenceController.java b/src/com/android/settings/notification/ZenModeScreenOnPreferenceController.java
deleted file mode 100644
index bab4dd1..0000000
--- a/src/com/android/settings/notification/ZenModeScreenOnPreferenceController.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.notification;
-
-import android.app.NotificationManager.Policy;
-import android.content.Context;
-import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.Preference;
-import android.util.Log;
-
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-public class ZenModeScreenOnPreferenceController extends
- AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener {
-
- protected static final String KEY = "zen_mode_screen_on";
-
- public ZenModeScreenOnPreferenceController(Context context, Lifecycle lifecycle) {
- super(context, KEY, lifecycle);
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY;
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public void updateState(Preference preference) {
- super.updateState(preference);
-
- SwitchPreference pref = (SwitchPreference) preference;
- pref.setChecked(mBackend.isEffectAllowed(Policy.SUPPRESSED_EFFECT_SCREEN_ON));
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final boolean bypass = (Boolean) newValue;
- if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allowWhenScreenOn="
- + bypass);
- mMetricsFeatureProvider.action(mContext,
- MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_WHEN_SCREEN_ON, bypass);
- mBackend.saveVisualEffectsPolicy(Policy.SUPPRESSED_EFFECT_SCREEN_ON, bypass);
- return true;
- }
-}
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 4e8793b..b143b42 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.provider.SearchIndexableResource;
import android.provider.Settings;
+import android.service.notification.ZenModeConfig;
import android.support.annotation.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -63,6 +64,9 @@
Lifecycle lifecycle, FragmentManager fragmentManager) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModeBehaviorPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeBlockedEffectsPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeDurationPreferenceController(context, lifecycle,
+ fragmentManager));
controllers.add(new ZenModeAutomationPreferenceController(context));
controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle));
@@ -121,9 +125,15 @@
int zenMode = NotificationManager.from(mContext).getZenMode();
if (zenMode != Settings.Global.ZEN_MODE_OFF) {
- Policy policy = NotificationManager.from(mContext).getNotificationPolicy();
- return mContext.getString(R.string.zen_mode_sound_summary_on,
- getBehaviorSettingSummary(policy, zenMode));
+ ZenModeConfig config = NotificationManager.from(mContext).getZenModeConfig();
+ String description = ZenModeConfig.getDescription(mContext, true, config);
+
+ if (description == null) {
+ return mContext.getString(R.string.zen_mode_sound_summary_on);
+ } else {
+ return mContext.getString(R.string.zen_mode_sound_summary_on_with_info,
+ description);
+ }
} else {
final int count = getEnabledAutomaticRulesCount();
if (count > 0) {
@@ -137,6 +147,18 @@
}
}
+ String getBlockedEffectsSummary(Policy policy) {
+ if (policy.suppressedVisualEffects == 0) {
+ return mContext.getResources().getString(
+ R.string.zen_mode_block_effect_summary_sound);
+ } else if (Policy.areAllVisualEffectsSuppressed(policy.suppressedVisualEffects)) {
+ return mContext.getResources().getString(
+ R.string.zen_mode_block_effect_summary_all);
+ }
+ return mContext.getResources().getString(
+ R.string.zen_mode_block_effect_summary_some);
+ }
+
String getAutomaticRulesSummary() {
final int count = getEnabledAutomaticRulesCount();
return count == 0 ? mContext.getString(R.string.zen_mode_settings_summary_off)
@@ -230,6 +252,7 @@
@Override
public List<String> getNonIndexableKeys(Context context) {
List<String> keys = super.getNonIndexableKeys(context);
+ keys.add(ZenModeDurationPreferenceController.KEY);
keys.add(ZenModeButtonPreferenceController.KEY);
return keys;
}
diff --git a/src/com/android/settings/notification/ZenModeVisEffectPreferenceController.java b/src/com/android/settings/notification/ZenModeVisEffectPreferenceController.java
new file mode 100644
index 0000000..89b953d
--- /dev/null
+++ b/src/com/android/settings/notification/ZenModeVisEffectPreferenceController.java
@@ -0,0 +1,91 @@
+/*
+ * 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.notification;
+
+import android.content.Context;
+import android.support.v7.preference.CheckBoxPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenModeVisEffectPreferenceController
+ extends AbstractZenModePreferenceController
+ implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+
+ protected final String mKey;
+ protected final int mEffect;
+ protected final int mMetricsCategory;
+ // if any of these effects are suppressed, this effect must be too
+ protected final int[] mParentSuppressedEffects;
+ private PreferenceScreen mScreen;
+
+ public ZenModeVisEffectPreferenceController(Context context, Lifecycle lifecycle, String key,
+ int visualEffect, int metricsCategory, int[] parentSuppressedEffects) {
+ super(context, key, lifecycle);
+ mKey = key;
+ mEffect = visualEffect;
+ mMetricsCategory = metricsCategory;
+ mParentSuppressedEffects = parentSuppressedEffects;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return mKey;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ mScreen = screen;
+ super.displayPreference(screen);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ boolean suppressed = mBackend.isVisualEffectSuppressed(mEffect);
+ boolean parentSuppressed = false;
+ if (mParentSuppressedEffects != null) {
+ for (int parentEffect : mParentSuppressedEffects) {
+ parentSuppressed |= mBackend.isVisualEffectSuppressed(parentEffect);
+ }
+ }
+ if (parentSuppressed) {
+ ((CheckBoxPreference) preference).setChecked(parentSuppressed);
+ onPreferenceChange(preference, parentSuppressed);
+ preference.setEnabled(false);
+ } else {
+ preference.setEnabled(true);
+ ((CheckBoxPreference) preference).setChecked(suppressed);
+ }
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final boolean suppressEffect = (Boolean) newValue;
+
+ mMetricsFeatureProvider.action(mContext, mMetricsCategory, suppressEffect);
+ mBackend.saveVisualEffectsPolicy(mEffect, suppressEffect);
+ return true;
+ }
+}
diff --git a/src/com/android/settings/password/SetupChooseLockPattern.java b/src/com/android/settings/password/SetupChooseLockPattern.java
index 864c5c2..8853950 100644
--- a/src/com/android/settings/password/SetupChooseLockPattern.java
+++ b/src/com/android/settings/password/SetupChooseLockPattern.java
@@ -20,7 +20,10 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
@@ -54,16 +57,20 @@
public static class SetupChooseLockPatternFragment extends ChooseLockPatternFragment
implements ChooseLockTypeDialogFragment.OnLockTypeSelectedListener {
+ @Nullable
+ private Button mOptionsButton;
+
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = super.onCreateView(inflater, container, savedInstanceState);
if (!getResources().getBoolean(R.bool.config_lock_pattern_minimal_ui)) {
- Button optionsButton = view.findViewById(R.id.screen_lock_options);
- optionsButton.setVisibility(View.VISIBLE);
- optionsButton.setOnClickListener((btn) ->
+ mOptionsButton = view.findViewById(R.id.screen_lock_options);
+ mOptionsButton.setOnClickListener((btn) ->
ChooseLockTypeDialogFragment.newInstance(mUserId)
.show(getChildFragmentManager(), null));
}
+ return view;
}
@Override
@@ -85,6 +92,16 @@
}
@Override
+ protected void updateStage(Stage stage) {
+ super.updateStage(stage);
+ if (!getResources().getBoolean(R.bool.config_lock_pattern_minimal_ui)
+ && mOptionsButton != null) {
+ mOptionsButton.setVisibility(
+ stage == Stage.Introduction ? View.VISIBLE : View.INVISIBLE);
+ }
+ }
+
+ @Override
public void handleLeftButton() {
SetupSkipDialog dialog = SetupSkipDialog.newInstance(
getActivity().getIntent()
diff --git a/src/com/android/settings/search/SearchIndexableResourcesImpl.java b/src/com/android/settings/search/SearchIndexableResourcesImpl.java
index 1798d34..61f5fec 100644
--- a/src/com/android/settings/search/SearchIndexableResourcesImpl.java
+++ b/src/com/android/settings/search/SearchIndexableResourcesImpl.java
@@ -74,6 +74,7 @@
import com.android.settings.notification.SoundSettings;
import com.android.settings.notification.ZenModeAutomationSettings;
import com.android.settings.notification.ZenModeBehaviorSettings;
+import com.android.settings.notification.ZenModeBlockedEffectsSettings;
import com.android.settings.notification.ZenModeSettings;
import com.android.settings.print.PrintSettingsFragment;
import com.android.settings.security.EncryptionAndCredential;
@@ -175,6 +176,7 @@
addIndex(UsbDetailsFragment.class);
addIndex(WifiDisplaySettings.class);
addIndex(ZenModeBehaviorSettings.class);
+ addIndex(ZenModeBlockedEffectsSettings.class);
addIndex(ZenModeAutomationSettings.class);
addIndex(NightDisplaySettings.class);
addIndex(SmartBatterySettings.class);
diff --git a/src/com/android/settings/security/EncryptionStatusPreferenceController.java b/src/com/android/settings/security/EncryptionStatusPreferenceController.java
index 2341248..8125599 100644
--- a/src/com/android/settings/security/EncryptionStatusPreferenceController.java
+++ b/src/com/android/settings/security/EncryptionStatusPreferenceController.java
@@ -41,6 +41,12 @@
@Override
public int getAvailabilityStatus() {
+ if (TextUtils.equals(getPreferenceKey(), PREF_KEY_ENCRYPTION_DETAIL_PAGE) &&
+ !mContext.getResources().getBoolean(
+ R.bool.config_show_encryption_and_credentials_encryption_status)) {
+ return DISABLED_UNSUPPORTED;
+ }
+
return mUserManager.isAdminUser() ? AVAILABLE : DISABLED_FOR_USER;
}
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index d8ba991..68c9731 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -24,6 +24,7 @@
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.net.wifi.WifiManager;
+import android.provider.SettingsSlicesContract;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
@@ -63,6 +64,10 @@
private static final String TAG = "SettingsSliceProvider";
+ /**
+ * Authority for Settings slices not officially supported by the platform, but extensible for
+ * OEMs.
+ */
public static final String SLICE_AUTHORITY = "com.android.settings.slices";
public static final String PATH_WIFI = "wifi";
@@ -82,13 +87,6 @@
@VisibleForTesting
Map<Uri, SliceData> mSliceDataCache;
- public static Uri getUri(String path) {
- return new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority(SLICE_AUTHORITY)
- .appendPath(path).build();
- }
-
@Override
public boolean onCreateSliceProvider() {
mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(getContext());
@@ -176,7 +174,8 @@
.setSubtitle(state)
.addEndItem(new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED),
null, finalWifiEnabled))
- .setPrimaryAction(new SliceAction(getIntent(Intent.ACTION_MAIN), null, null)))
+ .setPrimaryAction(
+ new SliceAction(getIntent(Intent.ACTION_MAIN), null, null)))
.build();
}
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index a68ed19..4124df7 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -59,7 +59,8 @@
// Wait a bit for wifi to update (TODO: is there a better way to do this?)
Handler h = new Handler();
h.postDelayed(() -> {
- Uri uri = SettingsSliceProvider.getUri(SettingsSliceProvider.PATH_WIFI);
+ Uri uri = SliceBuilderUtils.getUri(SettingsSliceProvider.PATH_WIFI,
+ false /* isPlatformSlice */);
context.getContentResolver().notifyChange(uri, null);
}, 1000);
break;
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index e94ee56..e90ea8e 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -19,9 +19,12 @@
import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
import android.app.PendingIntent;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.provider.SettingsSlicesContract;
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
@@ -98,6 +101,17 @@
sliceData.getKey());
}
+ public static Uri getUri(String path, boolean isPlatformSlice) {
+ final String authority = isPlatformSlice
+ ? SettingsSlicesContract.AUTHORITY
+ : SettingsSliceProvider.SLICE_AUTHORITY;
+ return new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(authority)
+ .appendPath(path)
+ .build();
+ }
+
private static BasePreferenceController getPreferenceController(Context context,
String controllerClassName, String controllerKey) {
try {
diff --git a/src/com/android/settings/slices/SliceData.java b/src/com/android/settings/slices/SliceData.java
index a7c9a11..c02b113 100644
--- a/src/com/android/settings/slices/SliceData.java
+++ b/src/com/android/settings/slices/SliceData.java
@@ -70,6 +70,8 @@
@SliceType
private final int mSliceType;
+ private final boolean mIsPlatformDefined;
+
public String getKey() {
return mKey;
}
@@ -106,6 +108,10 @@
return mSliceType;
}
+ public boolean isPlatformDefined() {
+ return mIsPlatformDefined;
+ }
+
private SliceData(Builder builder) {
mKey = builder.mKey;
mTitle = builder.mTitle;
@@ -116,6 +122,7 @@
mUri = builder.mUri;
mPreferenceController = builder.mPrefControllerClassName;
mSliceType = builder.mSliceType;
+ mIsPlatformDefined = builder.mIsPlatformDefined;
}
@Override
@@ -151,6 +158,8 @@
private int mSliceType;
+ private boolean mIsPlatformDefined;
+
public Builder setKey(String key) {
mKey = key;
return this;
@@ -196,6 +205,11 @@
return this;
}
+ public Builder setPlatformDefined(boolean isPlatformDefined) {
+ mIsPlatformDefined = isPlatformDefined;
+ return this;
+ }
+
public SliceData build() {
if (TextUtils.isEmpty(mKey)) {
throw new IllegalStateException("Key cannot be empty");
diff --git a/src/com/android/settings/slices/SliceDataConverter.java b/src/com/android/settings/slices/SliceDataConverter.java
index e7b53d0..7cf1994 100644
--- a/src/com/android/settings/slices/SliceDataConverter.java
+++ b/src/com/android/settings/slices/SliceDataConverter.java
@@ -19,6 +19,7 @@
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_CONTROLLER;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_ICON;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
+import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_PLATFORM_SLICE_FLAG;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SUMMARY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_TITLE;
@@ -164,7 +165,8 @@
| MetadataFlag.FLAG_NEED_PREF_TYPE
| MetadataFlag.FLAG_NEED_PREF_TITLE
| MetadataFlag.FLAG_NEED_PREF_ICON
- | MetadataFlag.FLAG_NEED_PREF_SUMMARY);
+ | MetadataFlag.FLAG_NEED_PREF_SUMMARY
+ | MetadataFlag.FLAG_NEED_PLATFORM_SLICE_FLAG);
for (Bundle bundle : metadata) {
// TODO (b/67996923) Non-controller Slices should become intent-only slices.
@@ -179,6 +181,7 @@
final int iconResId = bundle.getInt(METADATA_ICON);
final int sliceType = SliceBuilderUtils.getSliceType(mContext, controllerClassName,
key);
+ final boolean isPlatformSlice = bundle.getBoolean(METADATA_PLATFORM_SLICE_FLAG);
final SliceData xmlSlice = new SliceData.Builder()
.setKey(key)
@@ -189,6 +192,7 @@
.setPreferenceControllerClassName(controllerClassName)
.setFragmentName(fragmentName)
.setSliceType(sliceType)
+ .setPlatformDefined(isPlatformSlice)
.build();
xmlSliceData.add(xmlSlice);
diff --git a/src/com/android/settings/system/ResetPreferenceController.java b/src/com/android/settings/system/ResetPreferenceController.java
new file mode 100644
index 0000000..16f7ce3
--- /dev/null
+++ b/src/com/android/settings/system/ResetPreferenceController.java
@@ -0,0 +1,35 @@
+/*
+ * 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.system;
+
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+
+public class ResetPreferenceController extends BasePreferenceController {
+
+ public ResetPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return mContext.getResources().getBoolean(R.bool.config_show_reset_dashboard)
+ ? AVAILABLE
+ : DISABLED_UNSUPPORTED;
+ }
+}
diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml
index 788c593..39620d8 100644
--- a/tests/robotests/res/values-mcc999/config.xml
+++ b/tests/robotests/res/values-mcc999/config.xml
@@ -34,6 +34,7 @@
<bool name="config_show_screen_locking_sounds">false</bool>
<bool name="config_show_touch_sounds">false</bool>
<bool name="config_show_device_administrators">false</bool>
+ <bool name="config_show_encryption_and_credentials_encryption_status">false</bool>
<bool name="config_show_premium_sms">false</bool>
<bool name="config_show_data_saver">false</bool>
<bool name="config_show_enabled_vr_listeners">false</bool>
@@ -54,6 +55,7 @@
<bool name="config_show_tts_settings_summary">false</bool>
<bool name="config_show_pointer_speed">false</bool>
<bool name="config_show_vibrate_input_devices">false</bool>
+ <bool name="config_show_reset_dashboard">false</bool>
<bool name="config_show_system_update_settings">false</bool>
<bool name="config_wifi_support_connected_mac_randomization">false</bool>
<bool name="config_show_device_model">false</bool>
diff --git a/tests/robotests/res/xml-mcc999/location_settings.xml b/tests/robotests/res/xml-mcc999/location_settings.xml
index de77bfa..e04f1be 100644
--- a/tests/robotests/res/xml-mcc999/location_settings.xml
+++ b/tests/robotests/res/xml-mcc999/location_settings.xml
@@ -24,6 +24,7 @@
android:title="title"
android:icon="@drawable/ic_android"
android:summary="summary"
- settings:controller="com.android.settings.slices.FakePreferenceController"/>
+ settings:controller="com.android.settings.slices.FakePreferenceController"
+ settings:platform_slice="true"/>
</PreferenceScreen>
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothFilesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFilesPreferenceControllerTest.java
index 2c1e46d..4335f05 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothFilesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFilesPreferenceControllerTest.java
@@ -18,6 +18,10 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.pm.PackageManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -28,6 +32,7 @@
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.ShadowApplication;
@@ -38,15 +43,18 @@
private Context mContext;
private BluetoothFilesPreferenceController mController;
private Preference mPreference;
+ @Mock
+ private PackageManager mPackageManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
-
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
mController = new BluetoothFilesPreferenceController(mContext);
mPreference = new Preference(mContext);
mPreference.setKey(BluetoothFilesPreferenceController.KEY_RECEIVED_FILES);
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java
index 3656b38..373c255 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceGroupControllerTest.java
@@ -15,6 +15,8 @@
*/
package com.android.settings.connecteddevice;
+import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
@@ -24,6 +26,7 @@
import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceManager;
@@ -58,6 +61,8 @@
private PreferenceScreen mPreferenceScreen;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceManager mPreferenceManager;
+ @Mock
+ private PackageManager mPackageManager;
private PreferenceGroup mPreferenceGroup;
private Context mContext;
@@ -70,7 +75,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
mPreference = new Preference(mContext);
mPreference.setKey(PREFERENCE_KEY_1);
mLifecycleOwner = () -> mLifecycle;
@@ -78,6 +83,8 @@
mPreferenceGroup = spy(new PreferenceScreen(mContext, null));
when(mPreferenceGroup.getPreferenceManager()).thenReturn(mPreferenceManager);
doReturn(mContext).when(mDashboardFragment).getContext();
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
mConnectedDeviceGroupController = new ConnectedDeviceGroupController(mDashboardFragment,
mLifecycle, mConnectedBluetoothDeviceUpdater, mConnectedUsbDeviceUpdater);
@@ -134,4 +141,12 @@
verify(mConnectedBluetoothDeviceUpdater).unregisterCallback();
verify(mConnectedUsbDeviceUpdater).unregisterCallback();
}
+
+ @Test
+ public void testGetAvailabilityStatus_noBluetoothFeature_returnUnSupported() {
+ doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
+
+ assertThat(mConnectedDeviceGroupController.getAvailabilityStatus()).isEqualTo(
+ DISABLED_UNSUPPORTED);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/SavedDeviceGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/SavedDeviceGroupControllerTest.java
new file mode 100644
index 0000000..3d606dd
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/SavedDeviceGroupControllerTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.connecteddevice;
+
+import static android.arch.lifecycle.Lifecycle.Event.ON_START;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.arch.lifecycle.LifecycleOwner;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceGroup;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.bluetooth.BluetoothDeviceUpdater;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SavedDeviceGroupControllerTest {
+ private static final String PREFERENCE_KEY_1 = "pref_key_1";
+
+ @Mock
+ private DashboardFragment mDashboardFragment;
+ @Mock
+ private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private PreferenceManager mPreferenceManager;
+ @Mock
+ private PackageManager mPackageManager;
+
+ private PreferenceGroup mPreferenceGroup;
+ private Context mContext;
+ private Preference mPreference;
+ private SavedDeviceGroupController mConnectedDeviceGroupController;
+ private LifecycleOwner mLifecycleOwner;
+ private Lifecycle mLifecycle;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(RuntimeEnvironment.application);
+ mLifecycleOwner = () -> mLifecycle;
+ mLifecycle = new Lifecycle(mLifecycleOwner);
+
+ doReturn(mContext).when(mDashboardFragment).getContext();
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ }
+
+ @Test
+ public void constructor_noBluetoothFeature_shouldNotRegisterCallback() {
+ doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
+
+ mConnectedDeviceGroupController = new SavedDeviceGroupController(mDashboardFragment,
+ mLifecycle, mBluetoothDeviceUpdater);
+
+ assertThat(mConnectedDeviceGroupController.getAvailabilityStatus()).isEqualTo(
+ DISABLED_UNSUPPORTED);
+
+ mLifecycle.handleLifecycleEvent(ON_START);
+ verify(mBluetoothDeviceUpdater, never()).registerCallback();
+ }
+
+
+ @Test
+ public void constructor_hasBluetoothFeature_shouldRegisterCallback() {
+ doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
+
+ mConnectedDeviceGroupController = new SavedDeviceGroupController(mDashboardFragment,
+ mLifecycle, mBluetoothDeviceUpdater);
+
+ assertThat(mConnectedDeviceGroupController.getAvailabilityStatus()).isEqualTo(
+ AVAILABLE);
+
+ mLifecycle.handleLifecycleEvent(ON_START);
+ verify(mBluetoothDeviceUpdater).registerCallback();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java
index 533d4e9..dc492a9 100644
--- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java
@@ -44,6 +44,7 @@
import com.android.settings.dashboard.DashboardAdapter;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowCardView;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import com.android.settingslib.utils.IconCache;
@@ -54,12 +55,14 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = ShadowCardView.class)
public class SuggestionAdapterTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
diff --git a/tests/robotests/src/com/android/settings/datetime/timezone/FixedOffsetPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/timezone/FixedOffsetPreferenceControllerTest.java
index 0ffb7d2..f657560 100644
--- a/tests/robotests/src/com/android/settings/datetime/timezone/FixedOffsetPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/timezone/FixedOffsetPreferenceControllerTest.java
@@ -40,10 +40,9 @@
}
@Test
- public void updateState_matchTimeZoneSummary() {
+ public void updateState_GmtMinus8_matchTimeZoneSummary() {
TimeZoneInfo fixedOffsetZone = new TimeZoneInfo.Builder(
TimeZone.getFrozenTimeZone("Etc/GMT-8"))
- .setExemplarLocation("Los Angeles")
.setGmtOffset("GMT-08:00")
.setItemId(0)
.build();
@@ -52,6 +51,21 @@
controller.setTimeZoneInfo(fixedOffsetZone);
controller.updateState(preference);
assertThat(preference.getSummary()).isEqualTo("GMT-08:00");
+ }
+ @Test
+ public void updateState_Utc_matchTimeZoneSummary() {
+ TimeZoneInfo fixedOffsetZone = new TimeZoneInfo.Builder(
+ TimeZone.getFrozenTimeZone("Etc/UTC"))
+ .setStandardName("Coordinated Universal Time")
+ .setGmtOffset("GMT+00:00")
+ .setItemId(0)
+ .build();
+ Preference preference = new Preference(mActivity);
+ FixedOffsetPreferenceController controller = new FixedOffsetPreferenceController(mActivity);
+ controller.setTimeZoneInfo(fixedOffsetZone);
+ controller.updateState(preference);
+ assertThat(preference.getSummary().toString())
+ .isEqualTo("Coordinated Universal Time (GMT+00:00)");
}
}
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothDelayReportsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothDelayReportsPreferenceControllerTest.java
index d529fc1..bdaad0a 100644
--- a/tests/robotests/src/com/android/settings/development/BluetoothDelayReportsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/BluetoothDelayReportsPreferenceControllerTest.java
@@ -16,7 +16,9 @@
package com.android.settings.development;
-import static com.android.settings.development.BluetoothDelayReportsPreferenceController.BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY;
+import static com.android.settings.development.BluetoothDelayReportsPreferenceController
+ .BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -57,11 +59,11 @@
}
@Test
- public void onPreferenceChanged_settingEnabled_turnOnDelayReports() {
+ public void onPreferenceChanged_settingDisabled_turnOnDelayReports() {
mController.onPreferenceChange(mPreference, true /* new value */);
final boolean mode = SystemProperties.getBoolean(
- BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
+ BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
assertThat(mode).isTrue();
}
@@ -71,14 +73,14 @@
mController.onPreferenceChange(mPreference, false /* new value */);
final boolean mode = SystemProperties.getBoolean(
- BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
+ BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
assertThat(mode).isFalse();
}
@Test
- public void updateState_settingEnabled_preferenceShouldBeChecked() {
- SystemProperties.set(BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY,
+ public void updateState_settingDisabled_preferenceShouldBeChecked() {
+ SystemProperties.set(BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY,
Boolean.toString(true));
mController.updateState(mPreference);
@@ -87,7 +89,7 @@
@Test
public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
- SystemProperties.set(BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY,
+ SystemProperties.set(BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY,
Boolean.toString(false));
mController.updateState(mPreference);
@@ -99,10 +101,10 @@
mController.onDeveloperOptionsDisabled();
final boolean mode = SystemProperties.getBoolean(
- BLUETOOTH_ENABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
+ BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */);
assertThat(mode).isFalse();
assertThat(mPreference.isEnabled()).isFalse();
assertThat(mPreference.isChecked()).isFalse();
}
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
index 6360232..30999cb 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
@@ -40,7 +40,6 @@
@RunWith(RobolectricTestRunner.class)
public class BatteryDatabaseManagerTest {
-
private static String PACKAGE_NAME_NEW = "com.android.app1";
private static int UID_NEW = 345;
private static int TYPE_NEW = 1;
@@ -53,6 +52,9 @@
private Context mContext;
private BatteryDatabaseManager mBatteryDatabaseManager;
+ private AppInfo mNewAppInfo;
+ private AppInfo mOldAppInfo;
+ private AppInfo mCombinedAppInfo;
@Before
public void setUp() {
@@ -60,6 +62,23 @@
mContext = RuntimeEnvironment.application;
mBatteryDatabaseManager = spy(BatteryDatabaseManager.getInstance(mContext));
+
+ mNewAppInfo = new AppInfo.Builder()
+ .setUid(UID_NEW)
+ .setPackageName(PACKAGE_NAME_NEW)
+ .addAnomalyType(TYPE_NEW)
+ .build();
+ mOldAppInfo = new AppInfo.Builder()
+ .setUid(UID_OLD)
+ .setPackageName(PACKAGE_NAME_OLD)
+ .addAnomalyType(TYPE_OLD)
+ .build();
+ mCombinedAppInfo = new AppInfo.Builder()
+ .setUid(UID_NEW)
+ .setPackageName(PACKAGE_NAME_NEW)
+ .addAnomalyType(TYPE_NEW)
+ .addAnomalyType(TYPE_OLD)
+ .build();
}
@After
@@ -77,23 +96,19 @@
// In database, it contains two record
List<AppInfo> totalAppInfos = mBatteryDatabaseManager.queryAllAnomalies(0 /* timeMsAfter */,
AnomalyDatabaseHelper.State.NEW);
- assertThat(totalAppInfos).hasSize(2);
- assertAppInfo(totalAppInfos.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
- assertAppInfo(totalAppInfos.get(1), UID_OLD, PACKAGE_NAME_OLD, TYPE_OLD);
+ assertThat(totalAppInfos).containsExactly(mNewAppInfo, mOldAppInfo);
// Only one record shows up if we query by timestamp
List<AppInfo> appInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
AnomalyDatabaseHelper.State.NEW);
- assertThat(appInfos).hasSize(1);
- assertAppInfo(appInfos.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
+ assertThat(appInfos).containsExactly(mNewAppInfo);
mBatteryDatabaseManager.deleteAllAnomaliesBeforeTimeStamp(ONE_DAY_BEFORE);
// The obsolete record is removed from database
List<AppInfo> appInfos1 = mBatteryDatabaseManager.queryAllAnomalies(0 /* timeMsAfter */,
AnomalyDatabaseHelper.State.NEW);
- assertThat(appInfos1).hasSize(1);
- assertAppInfo(appInfos1.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
+ assertThat(appInfos1).containsExactly(mNewAppInfo);
}
@Test
@@ -113,19 +128,24 @@
// The state of PACKAGE_NAME_NEW is still new
List<AppInfo> newAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
AnomalyDatabaseHelper.State.NEW);
- assertThat(newAppInfos).hasSize(1);
- assertAppInfo(newAppInfos.get(0), UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW);
+ assertThat(newAppInfos).containsExactly(mNewAppInfo);
// The state of PACKAGE_NAME_OLD is changed to handled
List<AppInfo> handledAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
AnomalyDatabaseHelper.State.HANDLED);
- assertThat(handledAppInfos).hasSize(1);
- assertAppInfo(handledAppInfos.get(0), UID_OLD, PACKAGE_NAME_OLD, TYPE_OLD);
+ assertThat(handledAppInfos).containsExactly(mOldAppInfo);
}
- private void assertAppInfo(final AppInfo appInfo, int uid, String packageName, int type) {
- assertThat(appInfo.packageName).isEqualTo(packageName);
- assertThat(appInfo.anomalyType).isEqualTo(type);
- assertThat(appInfo.uid).isEqualTo(uid);
+ @Test
+ public void testQueryAnomalies_removeDuplicateByUid() {
+ mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW,
+ AnomalyDatabaseHelper.State.NEW, NOW);
+ mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_OLD,
+ AnomalyDatabaseHelper.State.NEW, NOW);
+
+ // Only contain one AppInfo with multiple types
+ List<AppInfo> newAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
+ AnomalyDatabaseHelper.State.NEW);
+ assertThat(newAppInfos).containsExactly(mCombinedAppInfo);
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceControllerTest.java
index d2c052a..72dde96 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/AutoBatterySeekBarPreferenceControllerTest.java
@@ -99,4 +99,24 @@
assertThat(Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)).isEqualTo(TRIGGER_LEVEL);
}
+
+ @Test
+ public void testOnPreferenceChange_changeMax() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 50);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getMax()).isEqualTo(50);
+ }
+
+ @Test
+ public void testOnPreferenceChange_noChangeMax() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 0);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getMax()).isEqualTo(100);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AppInfoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AppInfoTest.java
index b140c4c..74e8fe6 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AppInfoTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/AppInfoTest.java
@@ -36,7 +36,8 @@
public class AppInfoTest {
private static final String PACKAGE_NAME = "com.android.app";
- private static final int ANOMALY_TYPE = Anomaly.AnomalyType.WAKE_LOCK;
+ private static final int TYPE_WAKELOCK = Anomaly.AnomalyType.WAKE_LOCK;
+ private static final int TYPE_WAKEUP = Anomaly.AnomalyType.WAKEUP_ALARM;
private static final long SCREEN_TIME_MS = DateUtils.HOUR_IN_MILLIS;
private static final int UID = 3452;
@@ -46,7 +47,8 @@
public void setUp() {
mAppInfo = new AppInfo.Builder()
.setPackageName(PACKAGE_NAME)
- .setAnomalyType(ANOMALY_TYPE)
+ .addAnomalyType(TYPE_WAKELOCK)
+ .addAnomalyType(TYPE_WAKEUP)
.setScreenOnTimeMs(SCREEN_TIME_MS)
.setUid(UID)
.build();
@@ -61,7 +63,7 @@
final AppInfo appInfo = new AppInfo(parcel);
assertThat(appInfo.packageName).isEqualTo(PACKAGE_NAME);
- assertThat(appInfo.anomalyType).isEqualTo(ANOMALY_TYPE);
+ assertThat(appInfo.anomalyTypes).containsExactly(TYPE_WAKELOCK, TYPE_WAKEUP);
assertThat(appInfo.screenOnTimeMs).isEqualTo(SCREEN_TIME_MS);
assertThat(appInfo.uid).isEqualTo(UID);
}
@@ -70,7 +72,7 @@
public void testCompareTo_hasCorrectOrder() {
final AppInfo appInfo = new AppInfo.Builder()
.setPackageName(PACKAGE_NAME)
- .setAnomalyType(ANOMALY_TYPE)
+ .addAnomalyType(TYPE_WAKELOCK)
.setScreenOnTimeMs(SCREEN_TIME_MS + 100)
.build();
@@ -85,7 +87,7 @@
@Test
public void testBuilder() {
assertThat(mAppInfo.packageName).isEqualTo(PACKAGE_NAME);
- assertThat(mAppInfo.anomalyType).isEqualTo(ANOMALY_TYPE);
+ assertThat(mAppInfo.anomalyTypes).containsExactly(TYPE_WAKELOCK, TYPE_WAKEUP);
assertThat(mAppInfo.screenOnTimeMs).isEqualTo(SCREEN_TIME_MS);
assertThat(mAppInfo.uid).isEqualTo(UID);
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java
index a3dabba..9f1bb31 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java
@@ -17,6 +17,7 @@
package com.android.settings.fuelgauge.batterytip;
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.spy;
import static org.robolectric.Shadows.shadowOf;
@@ -29,7 +30,6 @@
import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
-import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -67,7 +67,6 @@
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
- FakeFeatureFactory.setupForTest();
List<AppInfo> highUsageTips = new ArrayList<>();
final AppInfo appInfo = new AppInfo.Builder()
@@ -102,7 +101,7 @@
ShadowAlertDialog shadowDialog = shadowOf(dialog);
assertThat(shadowDialog.getMessage())
- .isEqualTo(mContext.getString(R.string.battery_tip_dialog_message, "1h"));
+ .isEqualTo(mContext.getString(R.string.battery_tip_dialog_message, "1h"));
}
@Test
@@ -116,7 +115,7 @@
assertThat(shadowDialog.getTitle()).isEqualTo("Restrict app?");
assertThat(shadowDialog.getMessage())
- .isEqualTo(mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
+ .isEqualTo(mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
}
@Test
@@ -134,7 +133,7 @@
assertThat(shadowDialog.getTitle()).isEqualTo("Restrict 2 apps?");
assertThat(shadowDialog.getMessage())
- .isEqualTo(mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
+ .isEqualTo(mContext.getString(R.string.battery_tip_restrict_app_dialog_message));
assertThat(shadowDialog.getView()).isNotNull();
}
@@ -150,6 +149,6 @@
assertThat(shadowDialog.getTitle()).isEqualTo("Remove restriction for app?");
assertThat(shadowDialog.getMessage())
- .isEqualTo(mContext.getString(R.string.battery_tip_unrestrict_app_dialog_message));
+ .isEqualTo(mContext.getString(R.string.battery_tip_unrestrict_app_dialog_message));
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
index b5cb173..6f898b2 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceControllerTest.java
@@ -119,9 +119,9 @@
public void testUpdateBatteryTips_logBatteryTip() {
mBatteryTipPreferenceController.updateBatteryTips(mOldBatteryTips);
- verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
- eq(MetricsProto.MetricsEvent.ACTION_BATTERY_TIP_SHOWN),
- eq(BatteryTip.TipType.SUMMARY));
+ verify(mFeatureFactory.metricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_SUMMARY_TIP,
+ BatteryTip.StateType.NEW);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java
index 753fc48..cee647e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java
@@ -25,6 +25,7 @@
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Test;
@@ -122,6 +123,11 @@
// do nothing
}
+ @Override
+ public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
+ // do nothing
+ }
+
public final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public BatteryTip createFromParcel(Parcel in) {
return new TestBatteryTip(in);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTipTest.java
index c30563d..1cac495 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTipTest.java
@@ -17,28 +17,38 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+
import android.content.Context;
import android.os.Parcel;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
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;
@RunWith(SettingsRobolectricTestRunner.class)
public class EarlyWarningTipTest {
+ @Mock
+ private MetricsFeatureProvider mMetricsFeatureProvider;
private Context mContext;
private EarlyWarningTip mEarlyWarningTip;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
mContext = RuntimeEnvironment.application;
mEarlyWarningTip =
- new EarlyWarningTip(BatteryTip.StateType.NEW, false /* powerSaveModeOn */);
+ new EarlyWarningTip(BatteryTip.StateType.NEW, false /* powerSaveModeOn */);
}
@Test
@@ -55,7 +65,7 @@
@Test
public void testInfo_stateNew_displayPowerModeInfo() {
final EarlyWarningTip tip =
- new EarlyWarningTip(BatteryTip.StateType.NEW, false /* powerModeOn */);
+ new EarlyWarningTip(BatteryTip.StateType.NEW, false /* powerModeOn */);
assertThat(tip.getTitle(mContext)).isEqualTo("Turn on Low Battery Mode");
assertThat(tip.getSummary(mContext)).isEqualTo("Extend your battery life");
@@ -65,7 +75,7 @@
@Test
public void testInfo_stateHandled_displayPowerModeHandledInfo() {
final EarlyWarningTip tip =
- new EarlyWarningTip(BatteryTip.StateType.HANDLED, false /* powerModeOn */);
+ new EarlyWarningTip(BatteryTip.StateType.HANDLED, false /* powerModeOn */);
assertThat(tip.getTitle(mContext)).isEqualTo("Low Battery Mode is on");
assertThat(tip.getSummary(mContext)).isEqualTo("Some features are limited");
@@ -75,7 +85,7 @@
@Test
public void testUpdate_powerModeTurnedOn_typeBecomeHandled() {
final EarlyWarningTip nextTip =
- new EarlyWarningTip(BatteryTip.StateType.INVISIBLE, true /* powerModeOn */);
+ new EarlyWarningTip(BatteryTip.StateType.INVISIBLE, true /* powerModeOn */);
mEarlyWarningTip.updateState(nextTip);
@@ -115,4 +125,12 @@
assertThat(earlyWarningTip.getState()).isEqualTo(BatteryTip.StateType.INVISIBLE);
}
+
+ @Test
+ public void testLog() {
+ mEarlyWarningTip.log(mContext, mMetricsFeatureProvider);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_EARLY_WARNING_TIP, BatteryTip.StateType.NEW);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java
index af32dc5..b038a91 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/HighUsageTipTest.java
@@ -17,16 +17,22 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+
import android.content.Context;
import android.os.Parcel;
import android.text.format.DateUtils;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
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 java.util.ArrayList;
@@ -38,14 +44,17 @@
private static final String PACKAGE_NAME = "com.android.app";
private static final long SCREEN_TIME = 30 * DateUtils.MINUTE_IN_MILLIS;
+ @Mock
+ private MetricsFeatureProvider mMetricsFeatureProvider;
private Context mContext;
private HighUsageTip mBatteryTip;
private List<AppInfo> mUsageAppList;
@Before
public void setUp() {
- mContext = RuntimeEnvironment.application;
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
mUsageAppList = new ArrayList<>();
mUsageAppList.add(new AppInfo.Builder()
.setPackageName(PACKAGE_NAME)
@@ -77,6 +86,18 @@
@Test
public void toString_containsAppData() {
assertThat(mBatteryTip.toString()).isEqualTo(
- "type=2 state=0 { packageName=com.android.app,anomalyType=0,screenTime=1800000 }");
+ "type=2 state=0 { packageName=com.android.app,anomalyTypes={},screenTime=1800000 "
+ + "}");
+ }
+
+ @Test
+ public void testLog_logAppInfo() {
+ mBatteryTip.log(mContext, mMetricsFeatureProvider);
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_HIGH_USAGE_TIP, BatteryTip.StateType.NEW);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_HIGH_USAGE_TIP_LIST,
+ PACKAGE_NAME);
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java
index 3298ea8..9d32b2b 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java
@@ -16,16 +16,25 @@
package com.android.settings.fuelgauge.batterytip.tips;
import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Parcel;
+import android.util.Pair;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.fuelgauge.batterytip.AppInfo;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Test;
@@ -39,9 +48,10 @@
@RunWith(SettingsRobolectricTestRunner.class)
public class RestrictAppTipTest {
-
private static final String PACKAGE_NAME = "com.android.app";
private static final String DISPLAY_NAME = "app";
+ private static final int ANOMALY_WAKEUP = 0;
+ private static final int ANOMALY_WAKELOCK = 1;
private Context mContext;
private RestrictAppTip mNewBatteryTip;
@@ -52,6 +62,8 @@
private ApplicationInfo mApplicationInfo;
@Mock
private PackageManager mPackageManager;
+ @Mock
+ private MetricsFeatureProvider mMetricsFeatureProvider;
@Before
public void setUp() throws Exception {
@@ -64,7 +76,11 @@
doReturn(DISPLAY_NAME).when(mApplicationInfo).loadLabel(mPackageManager);
mUsageAppList = new ArrayList<>();
- mUsageAppList.add(new AppInfo.Builder().setPackageName(PACKAGE_NAME).build());
+ mUsageAppList.add(new AppInfo.Builder()
+ .setPackageName(PACKAGE_NAME)
+ .addAnomalyType(ANOMALY_WAKEUP)
+ .addAnomalyType(ANOMALY_WAKELOCK)
+ .build());
mNewBatteryTip = new RestrictAppTip(BatteryTip.StateType.NEW, mUsageAppList);
mHandledBatteryTip = new RestrictAppTip(BatteryTip.StateType.HANDLED, mUsageAppList);
mInvisibleBatteryTip = new RestrictAppTip(BatteryTip.StateType.INVISIBLE, mUsageAppList);
@@ -125,6 +141,32 @@
@Test
public void toString_containsAppData() {
assertThat(mNewBatteryTip.toString()).isEqualTo(
- "type=1 state=0 { packageName=com.android.app,anomalyType=0,screenTime=0 }");
+ "type=1 state=0 { packageName=com.android.app,anomalyTypes={0, 1},screenTime=0 }");
+ }
+
+ @Test
+ public void testLog_stateNew_logAppInfo() {
+ mNewBatteryTip.log(mContext, mMetricsFeatureProvider);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP, BatteryTip.StateType.NEW);
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP_LIST,
+ PACKAGE_NAME,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, ANOMALY_WAKEUP));
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP_LIST,
+ PACKAGE_NAME,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, ANOMALY_WAKELOCK));
+ }
+
+ @Test
+ public void testLog_stateHandled_doNotLogAppInfo() {
+ mHandledBatteryTip.log(mContext, mMetricsFeatureProvider);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP, BatteryTip.StateType.HANDLED);
+ verify(mMetricsFeatureProvider, never()).action(any(), anyInt(), anyString(), any());
+
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTipTest.java
new file mode 100644
index 0000000..1e4aef8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/SmartBatteryTipTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.batterytip.tips;
+
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
+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;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SmartBatteryTipTest {
+
+ @Mock
+ private MetricsFeatureProvider mMetricsFeatureProvider;
+ private Context mContext;
+ private SmartBatteryTip mSmartBatteryTip;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = RuntimeEnvironment.application;
+ mSmartBatteryTip = new SmartBatteryTip(BatteryTip.StateType.NEW);
+ }
+
+ @Test
+ public void testLog() {
+ mSmartBatteryTip.log(mContext, mMetricsFeatureProvider);
+
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsProto.MetricsEvent.ACTION_SMART_BATTERY_TIP, BatteryTip.StateType.NEW);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java
index 13c99a6..3c8f3c4 100644
--- a/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/inputmethod/PhysicalKeyboardPreferenceControllerTest.java
@@ -55,7 +55,7 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mContext.getSystemService(Context.INPUT_SERVICE)).thenReturn(mIm);
+ when(mContext.getSystemService(InputManager.class)).thenReturn(mIm);
mController = new PhysicalKeyboardPreferenceController(mContext, null /* lifecycle */);
}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeBlockedEffectsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeBlockedEffectsPreferenceControllerTest.java
new file mode 100644
index 0000000..4bf05ef
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeBlockedEffectsPreferenceControllerTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.notification;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+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.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public final class ZenModeBlockedEffectsPreferenceControllerTest {
+
+ private ZenModeBlockedEffectsPreferenceController mController;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private NotificationManager.Policy mPolicy;
+
+ private Context mContext;
+ @Mock
+ private ZenModeBackend mBackend;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
+
+ mController = new ZenModeBlockedEffectsPreferenceController(
+ mContext, mock(Lifecycle.class));
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ }
+
+ @Test
+ public void testIsAvailable() {
+ assertTrue(mController.isAvailable());
+ }
+
+ @Test
+ public void testHasSummary() {
+ assertNotNull(mController.getSummary());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeDurationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeDurationPreferenceControllerTest.java
new file mode 100644
index 0000000..9a94e6c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeDurationPreferenceControllerTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.notification;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.FragmentManager;
+import android.app.NotificationManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+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.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ZenModeDurationPreferenceControllerTest {
+ private ZenModeDurationPreferenceController mController;
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private Preference mockPref;
+ @Mock
+ private NotificationManager.Policy mPolicy;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ private ContentResolver mContentResolver;
+ private Context mContext;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = shadowApplication.getApplicationContext();
+ mContentResolver = RuntimeEnvironment.application.getContentResolver();
+ mController = new ZenModeDurationPreferenceController(mContext, mock(Lifecycle.class),
+ mock(FragmentManager.class));
+ when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
+ mockPref);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void updateState_DurationForever() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+ Settings.Global.ZEN_DURATION_FOREVER);
+ final Preference mockPref = mock(Preference.class);
+ mController.updateState(mockPref);
+
+ verify(mockPref).setSummary(mContext.getString(R.string.zen_mode_duration_summary_forever));
+ }
+
+ @Test
+ public void updateState_DurationPrompt() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+ Settings.Global.ZEN_DURATION_PROMPT);
+ final Preference mockPref = mock(Preference.class);
+ mController.updateState(mockPref);
+
+ verify(mockPref).setSummary(mContext.getString(
+ R.string.zen_mode_duration_summary_always_prompt));
+ }
+
+ @Test
+ public void updateState_DurationCustom() {
+ int zenDuration = 45;
+ Settings.Global.putInt(mContentResolver, Settings.Global.ZEN_DURATION,
+ zenDuration);
+ final Preference mockPref = mock(Preference.class);
+ mController.updateState(mockPref);
+
+ verify(mockPref).setSummary(mContext.getResources().getString(
+ R.string.zen_mode_duration_summary_time_minutes, zenDuration));
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeScreenOffPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeScreenOffPreferenceControllerTest.java
deleted file mode 100644
index 6dd3c178..0000000
--- a/tests/robotests/src/com/android/settings/notification/ZenModeScreenOffPreferenceControllerTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.notification;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.NotificationManager;
-import android.content.Context;
-import android.support.v14.preference.SwitchPreference;
-
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-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.shadows.ShadowApplication;
-import org.robolectric.util.ReflectionHelpers;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class ZenModeScreenOffPreferenceControllerTest {
-
- private static final boolean MOCK_PRIORITY_SCREEN_OFF_SETTING = false;
-
- private ZenModeScreenOffPreferenceController mController;
-
- @Mock
- private ZenModeBackend mBackend;
- @Mock
- private NotificationManager mNotificationManager;
- @Mock
- private SwitchPreference mockPref;
- @Mock
- private NotificationManager.Policy mPolicy;
-
- private Context mContext;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- ShadowApplication shadowApplication = ShadowApplication.getInstance();
- shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
-
- mContext = shadowApplication.getApplicationContext();
- when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
-
- mController = new ZenModeScreenOffPreferenceController(mContext, mock(Lifecycle.class));
- ReflectionHelpers.setField(mController, "mBackend", mBackend);
- }
-
- @Test
- public void updateState() {
- final SwitchPreference mockPref = mock(SwitchPreference.class);
- when(mBackend.isEffectAllowed(NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF))
- .thenReturn(MOCK_PRIORITY_SCREEN_OFF_SETTING);
- mController.updateState(mockPref);
-
- verify(mockPref).setChecked(MOCK_PRIORITY_SCREEN_OFF_SETTING);
- }
-
- @Test
- public void onPreferenceChanged_EnableScreenOff() {
- boolean allow = true;
- mController.onPreferenceChange(mockPref, allow);
-
- verify(mBackend).saveVisualEffectsPolicy(
- NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF, allow);
- }
-
- @Test
- public void onPreferenceChanged_DisableScreenOff() {
- boolean allow = false;
- mController.onPreferenceChange(mockPref, allow);
-
- verify(mBackend).saveVisualEffectsPolicy(
- NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF, allow);
- }
-}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeScreenOnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeScreenOnPreferenceControllerTest.java
deleted file mode 100644
index 2fd1380..0000000
--- a/tests/robotests/src/com/android/settings/notification/ZenModeScreenOnPreferenceControllerTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.notification;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.NotificationManager;
-import android.content.Context;
-import android.support.v14.preference.SwitchPreference;
-
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-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.ShadowApplication;
-import org.robolectric.util.ReflectionHelpers;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class ZenModeScreenOnPreferenceControllerTest {
-
- private static final boolean MOCK_PRIORITY_SCREEN_ON_SETTING = false;
-
- private ZenModeScreenOnPreferenceController mController;
-
- @Mock
- private ZenModeBackend mBackend;
- @Mock
- private NotificationManager mNotificationManager;
- @Mock
- private SwitchPreference mockPref;
- @Mock
- private NotificationManager.Policy mPolicy;
-
- private Context mContext;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- ShadowApplication shadowApplication = ShadowApplication.getInstance();
- shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
-
- mContext = RuntimeEnvironment.application;
- when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
-
- mController = new ZenModeScreenOnPreferenceController(mContext, mock(Lifecycle.class));
- ReflectionHelpers.setField(mController, "mBackend", mBackend);
- }
-
- @Test
- public void updateState() {
- final SwitchPreference mockPref = mock(SwitchPreference.class);
- when(mBackend.isEffectAllowed(NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON))
- .thenReturn(MOCK_PRIORITY_SCREEN_ON_SETTING);
- mController.updateState(mockPref);
-
- verify(mockPref).setChecked(MOCK_PRIORITY_SCREEN_ON_SETTING);
- }
-
- @Test
- public void onPreferenceChanged_EnableScreenOn() {
- boolean allow = true;
- mController.onPreferenceChange(mockPref, allow);
-
- verify(mBackend)
- .saveVisualEffectsPolicy(NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON, allow);
- }
-
- @Test
- public void onPreferenceChanged_DisableScreenOn() {
- boolean allow = false;
- mController.onPreferenceChange(mockPref, allow);
-
- verify(mBackend)
- .saveVisualEffectsPolicy(NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON, allow);
- }
-}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectPreferenceControllerTest.java
new file mode 100644
index 0000000..a424491
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectPreferenceControllerTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.notification;
+
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.support.v7.preference.CheckBoxPreference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+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.shadows.ShadowApplication;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ZenModeVisEffectPreferenceControllerTest {
+ private ZenModeVisEffectPreferenceController mController;
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private CheckBoxPreference mockPref;
+ private Context mContext;
+ private FakeFeatureFactory mFeatureFactory;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock NotificationManager mNotificationManager;
+
+ private static final String PREF_KEY = "main_pref";
+ private static final int PREF_METRICS = 1;
+ private static final int PARENT_EFFECT1 = SUPPRESSED_EFFECT_BADGE;
+ private static final int PARENT_EFFECT2 = SUPPRESSED_EFFECT_NOTIFICATION_LIST;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ mContext = shadowApplication.getApplicationContext();
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+ when(mNotificationManager.getNotificationPolicy()).thenReturn(
+ mock(NotificationManager.Policy.class));
+ mController = new ZenModeVisEffectPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY, SUPPRESSED_EFFECT_PEEK, PREF_METRICS, null);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void updateState_notChecked() {
+ when(mBackend.isVisualEffectSuppressed(SUPPRESSED_EFFECT_PEEK)).thenReturn(false);
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(false);
+ verify(mockPref).setEnabled(true);
+ }
+
+ @Test
+ public void updateState_checked() {
+ when(mBackend.isVisualEffectSuppressed(SUPPRESSED_EFFECT_PEEK)).thenReturn(true);
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(true);
+ verify(mockPref).setEnabled(true);
+ }
+
+ @Test
+ public void updateState_checkedFalse_parentChecked() {
+ mController = new ZenModeVisEffectPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY, SUPPRESSED_EFFECT_PEEK, PREF_METRICS,
+ new int[] {PARENT_EFFECT1, PARENT_EFFECT2});
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.isVisualEffectSuppressed(SUPPRESSED_EFFECT_PEEK)).thenReturn(false);
+ when(mBackend.isVisualEffectSuppressed(PARENT_EFFECT1)).thenReturn(false);
+ when(mBackend.isVisualEffectSuppressed(PARENT_EFFECT2)).thenReturn(true);
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(true);
+ verify(mockPref).setEnabled(false);
+ verify(mBackend, times(1)).saveVisualEffectsPolicy(SUPPRESSED_EFFECT_PEEK, true);
+ }
+
+ @Test
+ public void updateState_checkedFalse_parentNotChecked() {
+ mController = new ZenModeVisEffectPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY, SUPPRESSED_EFFECT_PEEK, PREF_METRICS,
+ new int[] {PARENT_EFFECT1, PARENT_EFFECT2});
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.isVisualEffectSuppressed(SUPPRESSED_EFFECT_PEEK)).thenReturn(false);
+ when(mBackend.isVisualEffectSuppressed(PARENT_EFFECT1)).thenReturn(false);
+ when(mBackend.isVisualEffectSuppressed(PARENT_EFFECT2)).thenReturn(false);
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(false);
+ verify(mockPref).setEnabled(true);
+ verify(mBackend, never()).saveVisualEffectsPolicy(SUPPRESSED_EFFECT_PEEK, true);
+ }
+
+ @Test
+ public void onPreferenceChanged_checkedFalse() {
+ mController.onPreferenceChange(mockPref, false);
+
+ verify(mBackend).saveVisualEffectsPolicy(SUPPRESSED_EFFECT_PEEK, false);
+ verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
+ eq(PREF_METRICS),
+ eq(false));
+ }
+
+ @Test
+ public void onPreferenceChanged_checkedTrue() {
+ mController.onPreferenceChange(mockPref, true);
+ verify(mBackend).saveVisualEffectsPolicy(SUPPRESSED_EFFECT_PEEK, true);
+ verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
+ eq(PREF_METRICS),
+ eq(true));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
index e0df818..ab08a90 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
@@ -27,6 +27,7 @@
import android.view.View;
import android.widget.Button;
+import com.android.internal.widget.LockPatternView;
import com.android.settings.R;
import com.android.settings.SetupRedactionInterstitial;
import com.android.settings.password.ChooseLockPattern.ChooseLockPatternFragment;
@@ -44,6 +45,11 @@
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowAlertDialog;
import org.robolectric.shadows.ShadowPackageManager;
+import org.robolectric.util.ReflectionHelpers;
+import org.robolectric.util.ReflectionHelpers.ClassParameter;
+
+import java.util.Collections;
+import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {
@@ -85,6 +91,17 @@
@Config(qualifiers = "sw400dp")
@Test
+ public void selectPattern_shouldHideOptionsButton() {
+ Button button = mActivity.findViewById(R.id.screen_lock_options);
+ assertThat(button).isNotNull();
+ assertThat(button.getVisibility()).isEqualTo(View.VISIBLE);
+
+ LockPatternView lockPatternView = mActivity.findViewById(R.id.lockPattern);
+ ReflectionHelpers.callInstanceMethod(lockPatternView, "notifyPatternDetected");
+ }
+
+ @Config(qualifiers = "sw400dp")
+ @Test
public void sw400dp_shouldShowScreenLockOptions() {
Button button = mActivity.findViewById(R.id.screen_lock_options);
assertThat(button).isNotNull();
diff --git a/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
index ee6d33a..2e6b703 100644
--- a/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
@@ -68,6 +68,23 @@
}
@Test
+ @Config(qualifiers = "mcc999")
+ public void isAvailable_notVisible_false() {
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void isAvailable_notVisible_butNotDetailPage_true() {
+ mController = new EncryptionStatusPreferenceController(mContext,
+ PREF_KEY_ENCRYPTION_SECURITY_PAGE);
+
+ UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ Shadows.shadowOf(userManager).setIsAdminUser(true);
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
public void updateSummary_encrypted_shouldSayEncrypted() {
ShadowLockPatternUtils.setDeviceEncryptionEnabled(true);
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index 50f47ff..9edae7e 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -18,8 +18,7 @@
package com.android.settings.slices;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -28,6 +27,7 @@
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
+import android.provider.SettingsSlicesContract;
import com.android.settings.testutils.DatabaseTestUtils;
import com.android.settings.testutils.FakeToggleController;
@@ -50,6 +50,8 @@
public class SettingsSliceProviderTest {
private final String KEY = "KEY";
+ private final String INTENT_PATH = SettingsSlicesContract.PATH_SETTING_INTENT + "/" + KEY;
+ private final String ACTION_PATH = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + KEY;
private final String TITLE = "title";
private final String SUMMARY = "summary";
private final String SCREEN_TITLE = "screen title";
@@ -67,6 +69,8 @@
mProvider = spy(new SettingsSliceProvider());
mProvider.mSliceDataCache = new HashMap<>();
mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
+ when(mProvider.getContext()).thenReturn(mContext);
+
mDb = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase();
SlicesDatabaseHelper.getInstance(mContext).setIndexedState();
}
@@ -78,12 +82,8 @@
@Test
public void testInitialSliceReturned_emptySlice() {
- insertSpecialCase(KEY);
- ContentResolver mockResolver = mock(ContentResolver.class);
- doReturn(mockResolver).when(mContext).getContentResolver();
- when(mProvider.getContext()).thenReturn(mContext);
-
- Uri uri = SettingsSliceProvider.getUri(KEY);
+ insertSpecialCase(INTENT_PATH);
+ Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
Slice slice = mProvider.onBindSlice(uri);
assertThat(slice.getUri()).isEqualTo(uri);
@@ -91,21 +91,9 @@
}
@Test
- public void testUriBuilder_returnsValidSliceUri() {
- Uri uri = SettingsSliceProvider.getUri(KEY);
-
- assertThat(uri.getScheme()).isEqualTo(ContentResolver.SCHEME_CONTENT);
- assertThat(uri.getAuthority()).isEqualTo(SettingsSliceProvider.SLICE_AUTHORITY);
- assertThat(uri.getLastPathSegment()).isEqualTo(KEY);
- }
-
- @Test
public void testLoadSlice_returnsSliceFromAccessor() {
- ContentResolver mockResolver = mock(ContentResolver.class);
- doReturn(mockResolver).when(mContext).getContentResolver();
- when(mProvider.getContext()).thenReturn(mContext);
insertSpecialCase(KEY);
- Uri uri = SettingsSliceProvider.getUri(KEY);
+ Uri uri = SliceBuilderUtils.getUri(KEY, false);
mProvider.loadSlice(uri);
SliceData data = mProvider.mSliceDataCache.get(uri);
@@ -116,7 +104,6 @@
@Test
public void testLoadSlice_cachedEntryRemovedOnBuild() {
- when(mProvider.getContext()).thenReturn(mContext);
SliceData data = getDummyData();
mProvider.mSliceDataCache.put(data.getUri(), data);
mProvider.onBindSlice(data.getUri());
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 5a2271a..0fcce5f 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -20,8 +20,10 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
+import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
+import android.provider.SettingsSlicesContract;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
@@ -48,6 +50,9 @@
private final Class PREF_CONTROLLER = FakeToggleController.class;
private final Class PREF_CONTROLLER2 = FakeContextOnlyPreferenceController.class;
+ private final String INTENT_PATH = SettingsSlicesContract.PATH_SETTING_INTENT + "/" + KEY;
+ private final String ACTION_PATH = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + KEY;
+
private Context mContext;
@Before
@@ -63,6 +68,58 @@
}
@Test
+ public void testUriBuilder_oemAuthority_intentPath_returnsValidSliceUri() {
+ Uri expectedUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(INTENT_PATH)
+ .build();
+
+ Uri actualUri = SliceBuilderUtils.getUri(INTENT_PATH, false);
+
+ assertThat(actualUri).isEqualTo(expectedUri);
+ }
+
+ @Test
+ public void testUriBuilder_oemAuthority_actionPath_returnsValidSliceUri() {
+ Uri expectedUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(ACTION_PATH)
+ .build();
+
+ Uri actualUri = SliceBuilderUtils.getUri(ACTION_PATH, false);
+
+ assertThat(actualUri).isEqualTo(expectedUri);
+ }
+
+ @Test
+ public void testUriBuilder_platformAuthority_intentPath_returnsValidSliceUri() {
+ Uri expectedUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(ACTION_PATH)
+ .build();
+
+ Uri actualUri = SliceBuilderUtils.getUri(ACTION_PATH, true);
+
+ assertThat(actualUri).isEqualTo(expectedUri);
+ }
+
+ @Test
+ public void testUriBuilder_platformAuthority_actionPath_returnsValidSliceUri() {
+ Uri expectedUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(ACTION_PATH)
+ .build();
+
+ Uri actualUri = SliceBuilderUtils.getUri(ACTION_PATH, true);
+
+ assertThat(actualUri).isEqualTo(expectedUri);
+ }
+
+ @Test
public void testGetPreferenceController_buildsMatchingController() {
BasePreferenceController controller =
SliceBuilderUtils.getPreferenceController(mContext, getDummyData());
diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
index 4d6c08d..36c2754 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
@@ -81,6 +81,7 @@
assertThat(fakeSlice.getUri()).isNull();
assertThat(fakeSlice.getFragmentClassName()).isEqualTo(fakeFragmentClassName);
assertThat(fakeSlice.getPreferenceController()).isEqualTo(fakeControllerName);
- assertThat(fakeSlice.getSliceType()).isEqualTo(SliceData.SliceType.SLIDER);
+ assertThat(fakeSlice.getSliceType()).isEqualTo(SliceData.SliceType.SLIDER); // from XML
+ assertThat(fakeSlice.isPlatformDefined()).isTrue(); // from XML
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataTest.java
index 7cd19b5..c2ab0af 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceDataTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceDataTest.java
@@ -37,6 +37,7 @@
private final Uri URI = Uri.parse("content://com.android.settings.slices/test");
private final String PREF_CONTROLLER = "com.android.settings.slices.tester";
private final int SLICE_TYPE = SliceData.SliceType.SWITCH;
+ private final boolean IS_PLATFORM_DEFINED = true;
@Test
public void testBuilder_buildsMatchingObject() {
@@ -49,7 +50,8 @@
.setFragmentName(FRAGMENT_NAME)
.setUri(URI)
.setPreferenceControllerClassName(PREF_CONTROLLER)
- .setSliceType(SLICE_TYPE);
+ .setSliceType(SLICE_TYPE)
+ .setPlatformDefined(IS_PLATFORM_DEFINED);
SliceData data = builder.build();
@@ -62,6 +64,7 @@
assertThat(data.getUri()).isEqualTo(URI);
assertThat(data.getPreferenceController()).isEqualTo(PREF_CONTROLLER);
assertThat(data.getSliceType()).isEqualTo(SLICE_TYPE);
+ assertThat(data.isPlatformDefined()).isEqualTo(IS_PLATFORM_DEFINED);
}
@Test(expected = IllegalStateException.class)
diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
index 8989de9..331058c 100644
--- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
@@ -90,7 +90,7 @@
public void testGetSliceFromUri_validUri_validSliceReturned() {
String key = "key";
insertSpecialCase(key);
- Uri uri = SettingsSliceProvider.getUri(key);
+ Uri uri = SliceBuilderUtils.getUri(key, false);
SliceData data = mAccessor.getSliceDataFromUri(uri);
@@ -106,7 +106,7 @@
@Test(expected = IllegalStateException.class)
public void testGetSliceFromUri_invalidUri_errorThrown() {
- Uri uri = SettingsSliceProvider.getUri("durr");
+ Uri uri = SliceBuilderUtils.getUri("durr", false);
mAccessor.getSliceDataFromUri(uri);
}
diff --git a/tests/robotests/src/com/android/settings/system/ResetPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/system/ResetPreferenceControllerTest.java
new file mode 100644
index 0000000..3869903
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/system/ResetPreferenceControllerTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 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.system;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+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;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class ResetPreferenceControllerTest {
+
+ private static final String KEY_RESET_DASHBOARD = "reset_dashboard";
+
+ private Context mContext;
+ private ResetPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new ResetPreferenceController(mContext, KEY_RESET_DASHBOARD);
+ }
+
+ @Test
+ public void isAvailable_byDefault_true() {
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void isAvailable_ifNotVisible_false() {
+ assertThat(mController.isAvailable()).isFalse();
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowCardView.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowCardView.java
new file mode 100644
index 0000000..e349ee3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowCardView.java
@@ -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.testutils.shadow;
+
+import android.content.Context;
+import android.support.v7.widget.CardView;
+import android.util.AttributeSet;
+
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowFrameLayout;
+
+/**
+ * Shadow for CardView to get around view not implemented error.
+ */
+@Implements(CardView.class)
+public class ShadowCardView extends ShadowFrameLayout {
+
+ public void __constructor__(Context context, AttributeSet attrs, int defStyleAttr) {
+ // do nothing
+ }
+
+}