Snap for 6441286 from 8b4406dadb to mainline-release

Change-Id: Idbec9cdd4023fa93a66fb3ea889c51f2fb4d30fe
This commit is contained in:
android-build-team Robot
2020-04-29 07:11:52 +00:00
39 changed files with 826 additions and 197 deletions

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2020 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>

View File

@@ -0,0 +1,28 @@
<!--
Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
<path
android:fillColor="@android:color/white"
android:pathData="M18,8h-1.5V5.5C16.5,3.01 14.49,1 12,1S7.5,3.01 7.5,5.5V8H6c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V10C20,8.9 19.1,8 18,8zM9.5,5.5C9.5,4.12 10.62,3 12,3c1.38,0 2.5,1.12 2.5,2.5V8h-5V5.5zM18,20H6V10h1.5h9H18V20z"/>
</vector>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<ImageButton
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/button"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="?android:attr/selectableItemBackground"
android:scaleType="centerInside"
android:tint="?android:attr/textColorSecondary"
android:src="@drawable/ic_delete_x"/>

View File

@@ -1148,14 +1148,14 @@
<item>@string/zen_mode_from_anyone</item> <item>@string/zen_mode_from_anyone</item>
<item>@string/zen_mode_from_contacts</item> <item>@string/zen_mode_from_contacts</item>
<item>@string/zen_mode_from_starred</item> <item>@string/zen_mode_from_starred</item>
<item>@string/zen_mode_from_none_messages</item> <item>@string/zen_mode_none_messages</item>
</string-array> </string-array>
<string-array name="zen_mode_contacts_calls_entries" translatable="false"> <string-array name="zen_mode_contacts_calls_entries" translatable="false">
<item>@string/zen_mode_from_anyone</item> <item>@string/zen_mode_from_anyone</item>
<item>@string/zen_mode_from_contacts</item> <item>@string/zen_mode_from_contacts</item>
<item>@string/zen_mode_from_starred</item> <item>@string/zen_mode_from_starred</item>
<item>@string/zen_mode_from_none_calls</item> <item>@string/zen_mode_none_calls</item>
</string-array> </string-array>
<string-array name="zen_mode_contacts_values" translatable="false"> <string-array name="zen_mode_contacts_values" translatable="false">

View File

@@ -8465,6 +8465,8 @@
<!-- [CHAR LIMIT=150] Notification Importance title: important conversation level summary --> <!-- [CHAR LIMIT=150] Notification Importance title: important conversation level summary -->
<string name="notification_channel_summary_priority">Shows at top of conversation section and appears as a bubble.</string> <string name="notification_channel_summary_priority">Shows at top of conversation section and appears as a bubble.</string>
<string name="convo_not_supported_summary"><xliff:g id="app_name" example="Android Services">%1$s</xliff:g> does not support conversation-specific settings.</string>
<!-- Channel summaries for the app notification page --> <!-- Channel summaries for the app notification page -->
<!-- [CHAR LIMIT=150] Notification Importance title: min importance level summary --> <!-- [CHAR LIMIT=150] Notification Importance title: min importance level summary -->
@@ -8976,6 +8978,8 @@
<item quantity="one">1 other</item> <item quantity="one">1 other</item>
<item quantity="other"><xliff:g id="num_people" example="3">%d</xliff:g> others</item> <item quantity="other"><xliff:g id="num_people" example="3">%d</xliff:g> others</item>
</plurals> </plurals>
<!-- [CHAR LIMIT=40] Zen mode settings: Starred contacts summary when there are no starred contacts -->
<string name="zen_mode_starred_contacts_summary_none">None</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Messages option --> <!-- [CHAR LIMIT=40] Zen mode settings: Messages option -->
<string name="zen_mode_messages">Messages</string> <string name="zen_mode_messages">Messages</string>
@@ -8995,8 +8999,13 @@
<!-- Zen mode settings: All calls can bypass DND summary [CHAR LIMIT=NONE --> <!-- Zen mode settings: All calls can bypass DND summary [CHAR LIMIT=NONE -->
<string name="zen_mode_all_calls_summary">All calls can reach you</string> <string name="zen_mode_all_calls_summary">All calls can reach you</string>
<!-- Zen mode settings: Senders in contacts can bypass DND summary summary [CHAR LIMIT=NONE --> <!-- Zen mode settings: There are no contacts on the device [CHAR LIMIT=NONE] -->
<string name="zen_mode_contacts_senders_summary"><xliff:g id="num_contacts" example="120">%d</xliff:g> contacts</string> <string name="zen_mode_contacts_count_none">None</string>
<!-- Zen mode settings: Senders in contacts can bypass DND summary summary [CHAR LIMIT=NONE] -->
<plurals name="zen_mode_contacts_count">
<item quantity="one">1 contact</item>
<item quantity="other"><xliff:g id="num_contacts" example="120">%d</xliff:g> contacts</item>
</plurals>
<!-- [CHAR LIMIT=40] Zen mode settings: Calls or messages option value: From anyone --> <!-- [CHAR LIMIT=40] Zen mode settings: Calls or messages option value: From anyone -->
<string name="zen_mode_from_anyone">Anyone</string> <string name="zen_mode_from_anyone">Anyone</string>
@@ -9004,8 +9013,6 @@
<string name="zen_mode_from_contacts">Contacts</string> <string name="zen_mode_from_contacts">Contacts</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Calls or messages option value: From starred contacts only --> <!-- [CHAR LIMIT=40] Zen mode settings: Calls or messages option value: From starred contacts only -->
<string name="zen_mode_from_starred">Starred contacts</string> <string name="zen_mode_from_starred">Starred contacts</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Calls and/or messages from none-->
<string name="zen_mode_from_none">None</string>
<!-- Do not disturb settings, calls summary [CHAR LIMIT=100]--> <!-- Do not disturb settings, calls summary [CHAR LIMIT=100]-->
<string name="zen_calls_summary_starred_repeat">From starred contacts and repeat callers</string> <string name="zen_calls_summary_starred_repeat">From starred contacts and repeat callers</string>
@@ -9015,9 +9022,9 @@
<string name="zen_calls_summary_repeat_only">From repeat callers only</string> <string name="zen_calls_summary_repeat_only">From repeat callers only</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Calls option value: No calls allowed --> <!-- [CHAR LIMIT=40] Zen mode settings: Calls option value: No calls allowed -->
<string name="zen_mode_from_none_calls">Don\u2019t allow any calls</string> <string name="zen_mode_none_calls">None</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Messages option value: No messages allowed --> <!-- [CHAR LIMIT=40] Zen mode settings: Messages option value: No messages allowed -->
<string name="zen_mode_from_none_messages">Don\u2019t allow any messages</string> <string name="zen_mode_none_messages">None</string>
<!-- [CHAR LIMIT=80] Zen mode settings: Allow alarms option --> <!-- [CHAR LIMIT=80] Zen mode settings: Allow alarms option -->
<string name="zen_mode_alarms">Alarms</string> <string name="zen_mode_alarms">Alarms</string>

View File

@@ -27,4 +27,12 @@
android:title="@string/notification_bubbles_title" android:title="@string/notification_bubbles_title"
settings:allowDividerBelow="false"/> settings:allowDividerBelow="false"/>
<!-- Selected or excluded conversations get added here -->
<PreferenceCategory
android:title="@string/bubble_app_setting_selected_conversation_title"
android:key="bubble_conversations"
android:visibility="gone"
settings:allowDividerAbove="false"
settings:allowDividerBelow="false" />
</PreferenceScreen> </PreferenceScreen>

View File

@@ -78,14 +78,14 @@
android:key="ringtone" android:key="ringtone"
android:title="@string/notification_channel_sound_title" android:title="@string/notification_channel_sound_title"
android:dialogTitle="@string/notification_channel_sound_title" android:dialogTitle="@string/notification_channel_sound_title"
android:icon="@drawable/ic_media_stream" android:icon="@drawable/ic_notifications"
android:showSilent="true" android:showSilent="true"
android:showDefault="true"/> android:showDefault="true"/>
<!-- Visibility Override --> <!-- Visibility Override -->
<com.android.settings.RestrictedListPreference <com.android.settings.RestrictedListPreference
android:key="visibility_override" android:key="visibility_override"
android:icon="@drawable/ic_lock" android:icon="@drawable/ic_lock_closed"
android:title="@string/app_notification_visibility_override_title"/> android:title="@string/app_notification_visibility_override_title"/>
<!-- Show badge --> <!-- Show badge -->

View File

@@ -57,6 +57,7 @@ import android.net.LinkProperties;
import android.net.Network; import android.net.Network;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.BatteryManager; import android.os.BatteryManager;
import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
@@ -1089,4 +1090,15 @@ public final class Utils extends com.android.settingslib.Utils {
} }
return f; return f;
} }
/**
* Returns true if current binder uid is Settings Intelligence.
*/
public static boolean isSettingsIntelligence(Context context) {
final int callingUid = Binder.getCallingUid();
final String callingPackage = context.getPackageManager().getPackagesForUid(callingUid)[0];
final boolean isSettingsIntelligence = TextUtils.equals(callingPackage,
context.getString(R.string.config_settingsintelligence_package_name));
return isSettingsIntelligence;
}
} }

View File

@@ -269,7 +269,7 @@ public class AccessibilitySettings extends DashboardFragment {
final CharSequence serviceState; final CharSequence serviceState;
final int fragmentType = AccessibilityUtil.getAccessibilityServiceFragmentType(info); final int fragmentType = AccessibilityUtil.getAccessibilityServiceFragmentType(info);
if (fragmentType == AccessibilityServiceFragmentType.INVISIBLE) { if (fragmentType == AccessibilityServiceFragmentType.INVISIBLE_TOGGLE) {
final ComponentName componentName = new ComponentName( final ComponentName componentName = new ComponentName(
info.getResolveInfo().serviceInfo.packageName, info.getResolveInfo().serviceInfo.packageName,
info.getResolveInfo().serviceInfo.name); info.getResolveInfo().serviceInfo.name);
@@ -652,13 +652,16 @@ public class AccessibilitySettings extends DashboardFragment {
} }
private String getAccessibilityServiceFragmentTypeName(AccessibilityServiceInfo info) { private String getAccessibilityServiceFragmentTypeName(AccessibilityServiceInfo info) {
switch (AccessibilityUtil.getAccessibilityServiceFragmentType( // Shorten the name to avoid exceeding 100 characters in one line.
info)) { final String volumeShortcutToggleAccessibilityServicePreferenceFragment =
case AccessibilityServiceFragmentType.LEGACY: VolumeShortcutToggleAccessibilityServicePreferenceFragment.class.getName();
return LegacyAccessibilityServicePreferenceFragment.class.getName();
case AccessibilityServiceFragmentType.INVISIBLE: switch (AccessibilityUtil.getAccessibilityServiceFragmentType(info)) {
case AccessibilityServiceFragmentType.VOLUME_SHORTCUT_TOGGLE:
return volumeShortcutToggleAccessibilityServicePreferenceFragment;
case AccessibilityServiceFragmentType.INVISIBLE_TOGGLE:
return InvisibleToggleAccessibilityServicePreferenceFragment.class.getName(); return InvisibleToggleAccessibilityServicePreferenceFragment.class.getName();
case AccessibilityServiceFragmentType.INTUITIVE: case AccessibilityServiceFragmentType.TOGGLE:
return ToggleAccessibilityServicePreferenceFragment.class.getName(); return ToggleAccessibilityServicePreferenceFragment.class.getName();
default: default:
// impossible status // impossible status

View File

@@ -16,7 +16,7 @@
package com.android.settings.accessibility; package com.android.settings.accessibility;
import static com.android.settings.accessibility.AccessibilityUtil.AccessibilityServiceFragmentType.LEGACY; import static com.android.settings.accessibility.AccessibilityUtil.AccessibilityServiceFragmentType.VOLUME_SHORTCUT_TOGGLE;
import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
@@ -102,10 +102,10 @@ public class AccessibilitySettingsForSetupWizard extends SettingsPreferenceFragm
super.onResume(); super.onResume();
updateAccessibilityServicePreference(mScreenReaderPreference, updateAccessibilityServicePreference(mScreenReaderPreference,
SCREEN_READER_PACKAGE_NAME, SCREEN_READER_SERVICE_NAME, SCREEN_READER_PACKAGE_NAME, SCREEN_READER_SERVICE_NAME,
LegacyToggleScreenReaderPreferenceFragmentForSetupWizard.class.getName()); VolumeShortcutToggleScreenReaderPreferenceFragmentForSetupWizard.class.getName());
updateAccessibilityServicePreference(mSelectToSpeakPreference, updateAccessibilityServicePreference(mSelectToSpeakPreference,
SELECT_TO_SPEAK_PACKAGE_NAME, SELECT_TO_SPEAK_SERVICE_NAME, SELECT_TO_SPEAK_PACKAGE_NAME, SELECT_TO_SPEAK_SERVICE_NAME,
LegacyToggleSelectToSpeakPreferenceFragmentForSetupWizard.class.getName()); VolumeShortcutToggleSelectToSpeakPreferenceFragmentForSetupWizard.class.getName());
configureMagnificationPreferenceIfNeeded(mDisplayMagnificationPreference); configureMagnificationPreferenceIfNeeded(mDisplayMagnificationPreference);
} }
@@ -147,7 +147,7 @@ public class AccessibilitySettingsForSetupWizard extends SettingsPreferenceFragm
} }
private void updateAccessibilityServicePreference(Preference preference, private void updateAccessibilityServicePreference(Preference preference,
String packageName, String serviceName, String targetLegacyFragment) { String packageName, String serviceName, String targetFragment) {
final AccessibilityServiceInfo info = findService(packageName, serviceName); final AccessibilityServiceInfo info = findService(packageName, serviceName);
if (info == null) { if (info == null) {
getPreferenceScreen().removePreference(preference); getPreferenceScreen().removePreference(preference);
@@ -159,8 +159,8 @@ public class AccessibilitySettingsForSetupWizard extends SettingsPreferenceFragm
preference.setTitle(title); preference.setTitle(title);
ComponentName componentName = new ComponentName(serviceInfo.packageName, serviceInfo.name); ComponentName componentName = new ComponentName(serviceInfo.packageName, serviceInfo.name);
preference.setKey(componentName.flattenToString()); preference.setKey(componentName.flattenToString());
if (AccessibilityUtil.getAccessibilityServiceFragmentType(info) == LEGACY) { if (AccessibilityUtil.getAccessibilityServiceFragmentType(info) == VOLUME_SHORTCUT_TOGGLE) {
preference.setFragment(targetLegacyFragment); preference.setFragment(targetFragment);
} }
// Update the extras. // Update the extras.

View File

@@ -46,22 +46,23 @@ final class AccessibilityUtil {
/** /**
* Annotation for different accessibilityService fragment UI type. * Annotation for different accessibilityService fragment UI type.
* *
* {@code LEGACY} for displaying appearance aligned with sdk version Q accessibility service * {@code VOLUME_SHORTCUT_TOGGLE} for displaying basic accessibility service fragment but
* page, but only hardware shortcut allowed. * only hardware shortcut allowed.
* {@code INVISIBLE} for displaying appearance without switch bar. * {@code INVISIBLE_TOGGLE} for displaying basic accessibility service fragment without
* {@code INTUITIVE} for displaying appearance with new design. * switch bar.
* {@code TOGGLE} for displaying basic accessibility service fragment.
*/ */
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({ @IntDef({
AccessibilityServiceFragmentType.LEGACY, AccessibilityServiceFragmentType.VOLUME_SHORTCUT_TOGGLE,
AccessibilityServiceFragmentType.INVISIBLE, AccessibilityServiceFragmentType.INVISIBLE_TOGGLE,
AccessibilityServiceFragmentType.INTUITIVE, AccessibilityServiceFragmentType.TOGGLE,
}) })
public @interface AccessibilityServiceFragmentType { public @interface AccessibilityServiceFragmentType {
int LEGACY = 0; int VOLUME_SHORTCUT_TOGGLE = 0;
int INVISIBLE = 1; int INVISIBLE_TOGGLE = 1;
int INTUITIVE = 2; int TOGGLE = 2;
} }
// TODO(b/147021230): Will move common functions and variables to // TODO(b/147021230): Will move common functions and variables to
@@ -162,11 +163,11 @@ final class AccessibilityUtil {
& AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
if (targetSdk <= Build.VERSION_CODES.Q) { if (targetSdk <= Build.VERSION_CODES.Q) {
return AccessibilityServiceFragmentType.LEGACY; return AccessibilityServiceFragmentType.VOLUME_SHORTCUT_TOGGLE;
} }
return requestA11yButton return requestA11yButton
? AccessibilityServiceFragmentType.INVISIBLE ? AccessibilityServiceFragmentType.INVISIBLE_TOGGLE
: AccessibilityServiceFragmentType.INTUITIVE; : AccessibilityServiceFragmentType.TOGGLE;
} }
/** /**

View File

@@ -34,7 +34,7 @@ import com.google.common.collect.ImmutableSet;
* *
* <p>For accessibility services that target SDK <= Q. * <p>For accessibility services that target SDK <= Q.
*/ */
public class LegacyAccessibilityServicePreferenceFragment extends public class VolumeShortcutToggleAccessibilityServicePreferenceFragment extends
ToggleAccessibilityServicePreferenceFragment { ToggleAccessibilityServicePreferenceFragment {
@Override @Override

View File

@@ -21,8 +21,8 @@ import android.os.Bundle;
import android.view.View; import android.view.View;
/** For accessibility services that target SDK <= Q in setup wizard. */ /** For accessibility services that target SDK <= Q in setup wizard. */
public class LegacyToggleScreenReaderPreferenceFragmentForSetupWizard public class VolumeShortcutToggleScreenReaderPreferenceFragmentForSetupWizard
extends LegacyAccessibilityServicePreferenceFragment { extends VolumeShortcutToggleAccessibilityServicePreferenceFragment {
private boolean mToggleSwitchWasInitiallyChecked; private boolean mToggleSwitchWasInitiallyChecked;

View File

@@ -21,8 +21,8 @@ import android.os.Bundle;
import android.view.View; import android.view.View;
/** For accessibility services that target SDK <= Q in setup wizard. */ /** For accessibility services that target SDK <= Q in setup wizard. */
public class LegacyToggleSelectToSpeakPreferenceFragmentForSetupWizard public class VolumeShortcutToggleSelectToSpeakPreferenceFragmentForSetupWizard
extends LegacyAccessibilityServicePreferenceFragment { extends VolumeShortcutToggleAccessibilityServicePreferenceFragment {
private boolean mToggleSwitchWasInitiallyChecked; private boolean mToggleSwitchWasInitiallyChecked;

View File

@@ -114,6 +114,7 @@ public class DataUsageSummaryPreferenceController extends TelephonyBasePreferenc
*/ */
public void init(int subscriptionId) { public void init(int subscriptionId) {
mSubId = subscriptionId; mSubId = subscriptionId;
mHasMobileData = DataUsageUtils.hasMobileData(mContext);
mDataUsageController = null; mDataUsageController = null;
} }
@@ -123,8 +124,6 @@ public class DataUsageSummaryPreferenceController extends TelephonyBasePreferenc
context.getSystemService(NetworkPolicyManager.class); context.getSystemService(NetworkPolicyManager.class);
mPolicyEditor = new NetworkPolicyEditor(policyManager); mPolicyEditor = new NetworkPolicyEditor(policyManager);
mHasMobileData = DataUsageUtils.hasMobileData(context);
mDataUsageController = new DataUsageController(context); mDataUsageController = new DataUsageController(context);
mDataUsageController.setSubscriptionId(subscriptionId); mDataUsageController.setSubscriptionId(subscriptionId);
mDataInfoController = new DataUsageInfoController(); mDataInfoController = new DataUsageInfoController();
@@ -210,6 +209,11 @@ public class DataUsageSummaryPreferenceController extends TelephonyBasePreferenc
final DataUsageController.DataUsageInfo info = final DataUsageController.DataUsageInfo info =
mDataUsageController.getDataUsageInfo(mDefaultTemplate); mDataUsageController.getDataUsageInfo(mDefaultTemplate);
long usageLevel = info.usageLevel;
if (usageLevel <= 0L) {
usageLevel = mDataUsageController.getHistoricalUsageLevel(mDefaultTemplate);
}
if (subInfo != null) { if (subInfo != null) {
mDataInfoController.updateDataLimit(info, mPolicyEditor.getPolicy(mDefaultTemplate)); mDataInfoController.updateDataLimit(info, mPolicyEditor.getPolicy(mDefaultTemplate));
summaryPreference.setWifiMode(/* isWifiMode */ false, summaryPreference.setWifiMode(/* isWifiMode */ false,
@@ -218,7 +222,7 @@ public class DataUsageSummaryPreferenceController extends TelephonyBasePreferenc
summaryPreference.setWifiMode(/* isWifiMode */ true, /* usagePeriod */ summaryPreference.setWifiMode(/* isWifiMode */ true, /* usagePeriod */
info.period, /* isSingleWifi */ false); info.period, /* isSingleWifi */ false);
summaryPreference.setLimitInfo(null); summaryPreference.setLimitInfo(null);
summaryPreference.setUsageNumbers(info.usageLevel, summaryPreference.setUsageNumbers(usageLevel,
/* dataPlanSize */ -1L, /* dataPlanSize */ -1L,
/* hasMobileData */ true); /* hasMobileData */ true);
summaryPreference.setChartEnabled(false); summaryPreference.setChartEnabled(false);
@@ -231,6 +235,11 @@ public class DataUsageSummaryPreferenceController extends TelephonyBasePreferenc
} }
refreshDataplanInfo(info, subInfo); refreshDataplanInfo(info, subInfo);
if ((mDataplanUse <= 0L) && (mSnapshotTime < 0)) {
Log.d(TAG, "Display data usage from history");
mDataplanUse = usageLevel;
mSnapshotTime = -1L;
}
if (info.warningLevel > 0 && info.limitLevel > 0) { if (info.warningLevel > 0 && info.limitLevel > 0) {
summaryPreference.setLimitInfo(TextUtils.expandTemplate( summaryPreference.setLimitInfo(TextUtils.expandTemplate(

View File

@@ -70,6 +70,16 @@ import java.util.List;
public class StorageSettings extends SettingsPreferenceFragment implements Indexable { public class StorageSettings extends SettingsPreferenceFragment implements Indexable {
static final String TAG = "StorageSettings"; static final String TAG = "StorageSettings";
private static final String KEY_STORAGE_SETTINGS = "storage_settings";
private static final String KEY_INTERNAL_STORAGE = "storage_settings_internal_storage";
private static final String KEY_STORAGE_SETTINGS_VOLUME = "storage_settings_volume_";
private static final String KEY_STORAGE_SETTINGS_MEMORY_SIZE = "storage_settings_memory_size";
private static final String KEY_STORAGE_SETTINGS_MEMORY = "storage_settings_memory_available";
private static final String KEY_STORAGE_SETTINGS_DCIM = "storage_settings_dcim_space";
private static final String KEY_STORAGE_SETTINGS_MUSIC = "storage_settings_music_space";
private static final String KEY_STORAGE_SETTINGS_MISC = "storage_settings_misc_space";
private static final String KEY_STORAGE_SETTINGS_FREE_SPACE = "storage_settings_free_space";
private static final String TAG_VOLUME_UNMOUNTED = "volume_unmounted"; private static final String TAG_VOLUME_UNMOUNTED = "volume_unmounted";
private static final String TAG_DISK_INIT = "disk_init"; private static final String TAG_DISK_INIT = "disk_init";
private static final int METRICS_CATEGORY = SettingsEnums.DEVICEINFO_STORAGE; private static final int METRICS_CATEGORY = SettingsEnums.DEVICEINFO_STORAGE;
@@ -551,14 +561,14 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
SearchIndexableRaw data = new SearchIndexableRaw(context); SearchIndexableRaw data = new SearchIndexableRaw(context);
data.title = context.getString(R.string.storage_settings); data.title = context.getString(R.string.storage_settings);
data.key = "storage_settings"; data.key = KEY_STORAGE_SETTINGS;
data.screenTitle = context.getString(R.string.storage_settings); data.screenTitle = context.getString(R.string.storage_settings);
data.keywords = context.getString(R.string.keywords_storage_settings); data.keywords = context.getString(R.string.keywords_storage_settings);
result.add(data); result.add(data);
data = new SearchIndexableRaw(context); data = new SearchIndexableRaw(context);
data.title = context.getString(R.string.internal_storage); data.title = context.getString(R.string.internal_storage);
data.key = "storage_settings_internal_storage"; data.key = KEY_INTERNAL_STORAGE;
data.screenTitle = context.getString(R.string.storage_settings); data.screenTitle = context.getString(R.string.storage_settings);
result.add(data); result.add(data);
@@ -568,7 +578,7 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
for (VolumeInfo vol : vols) { for (VolumeInfo vol : vols) {
if (isInteresting(vol)) { if (isInteresting(vol)) {
data.title = storage.getBestVolumeDescription(vol); data.title = storage.getBestVolumeDescription(vol);
data.key = "storage_settings_volume_" + vol.id; data.key = KEY_STORAGE_SETTINGS_VOLUME + vol.id;
data.screenTitle = context.getString(R.string.storage_settings); data.screenTitle = context.getString(R.string.storage_settings);
result.add(data); result.add(data);
} }
@@ -576,37 +586,37 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
data = new SearchIndexableRaw(context); data = new SearchIndexableRaw(context);
data.title = context.getString(R.string.memory_size); data.title = context.getString(R.string.memory_size);
data.key = "storage_settings_memory_size"; data.key = KEY_STORAGE_SETTINGS_MEMORY_SIZE;
data.screenTitle = context.getString(R.string.storage_settings); data.screenTitle = context.getString(R.string.storage_settings);
result.add(data); result.add(data);
data = new SearchIndexableRaw(context); data = new SearchIndexableRaw(context);
data.title = context.getString(R.string.memory_available); data.title = context.getString(R.string.memory_available);
data.key = "storage_settings_memory_available"; data.key = KEY_STORAGE_SETTINGS_MEMORY;
data.screenTitle = context.getString(R.string.storage_settings); data.screenTitle = context.getString(R.string.storage_settings);
result.add(data); result.add(data);
data = new SearchIndexableRaw(context); data = new SearchIndexableRaw(context);
data.title = context.getString(R.string.memory_dcim_usage); data.title = context.getString(R.string.memory_dcim_usage);
data.key = "storage_settings_dcim_space"; data.key = KEY_STORAGE_SETTINGS_DCIM;
data.screenTitle = context.getString(R.string.storage_settings); data.screenTitle = context.getString(R.string.storage_settings);
result.add(data); result.add(data);
data = new SearchIndexableRaw(context); data = new SearchIndexableRaw(context);
data.title = context.getString(R.string.memory_music_usage); data.title = context.getString(R.string.memory_music_usage);
data.key = "storage_settings_music_space"; data.key = KEY_STORAGE_SETTINGS_MUSIC;
data.screenTitle = context.getString(R.string.storage_settings); data.screenTitle = context.getString(R.string.storage_settings);
result.add(data); result.add(data);
data = new SearchIndexableRaw(context); data = new SearchIndexableRaw(context);
data.title = context.getString(R.string.memory_media_misc_usage); data.title = context.getString(R.string.memory_media_misc_usage);
data.key = "storage_settings_misc_space"; data.key = KEY_STORAGE_SETTINGS_MISC;
data.screenTitle = context.getString(R.string.storage_settings); data.screenTitle = context.getString(R.string.storage_settings);
result.add(data); result.add(data);
data = new SearchIndexableRaw(context); data = new SearchIndexableRaw(context);
data.title = context.getString(R.string.storage_menu_free); data.title = context.getString(R.string.storage_menu_free);
data.key = "storage_settings_free_space"; data.key = KEY_STORAGE_SETTINGS_FREE_SPACE;
data.screenTitle = context.getString(R.string.storage_menu_free); data.screenTitle = context.getString(R.string.storage_menu_free);
// We need to define all three in order for this to trigger properly. // We need to define all three in order for this to trigger properly.
data.intentAction = StorageManager.ACTION_MANAGE_STORAGE; data.intentAction = StorageManager.ACTION_MANAGE_STORAGE;
@@ -618,5 +628,69 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
return result; return result;
} }
@Override
public List<String> getNonIndexableKeys(Context context) {
final List<String> niks = super.getNonIndexableKeys(context);
if (isExternalExist(context)) {
niks.add(KEY_STORAGE_SETTINGS);
niks.add(KEY_INTERNAL_STORAGE);
niks.add(KEY_STORAGE_SETTINGS_MEMORY_SIZE);
niks.add(KEY_STORAGE_SETTINGS_MEMORY);
niks.add(KEY_STORAGE_SETTINGS_DCIM);
niks.add(KEY_STORAGE_SETTINGS_MUSIC);
niks.add(KEY_STORAGE_SETTINGS_MISC);
niks.add(KEY_STORAGE_SETTINGS_FREE_SPACE);
final StorageManager storage = context.getSystemService(
StorageManager.class);
final List<VolumeInfo> vols = storage.getVolumes();
for (VolumeInfo vol : vols) {
if (isInteresting(vol)) {
niks.add(KEY_STORAGE_SETTINGS_VOLUME + vol.id);
}
}
}
return niks;
}
@Override
protected boolean isPageSearchEnabled(Context context) {
return !isExternalExist(context);
}
private boolean isExternalExist(Context context) {
int internalCount = 0;
StorageManager storageManager = context.getSystemService(StorageManager.class);
final List<VolumeInfo> volumes = storageManager.getVolumes();
for (VolumeInfo vol : volumes) {
//External storage
if (vol.getType() == VolumeInfo.TYPE_PUBLIC
|| vol.getType() == VolumeInfo.TYPE_STUB) {
return true;
} else if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
internalCount++;
}
}
// Unsupported disks
final List<DiskInfo> disks = storageManager.getDisks();
for (DiskInfo disk : disks) {
if (disk.volumeCount == 0 && disk.size > 0) {
return true;
}
}
// Missing private volumes
final List<VolumeRecord> recs = storageManager.getVolumeRecords();
for (VolumeRecord rec : recs) {
if (rec.getType() == VolumeInfo.TYPE_PRIVATE
&& storageManager.findVolumeByUuid(rec.getFsUuid()) == null) {
internalCount++;
}
}
return (internalCount != 1);
}
}; };
} }

View File

@@ -20,8 +20,10 @@ import android.content.Context;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.widget.GearPreference; import com.android.settings.widget.GearPreference;
import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.dream.DreamBackend; import com.android.settingslib.dream.DreamBackend;
import com.android.settingslib.dream.DreamBackend.DreamInfo; import com.android.settingslib.dream.DreamBackend.DreamInfo;
@@ -45,6 +47,7 @@ public class CurrentDreamPreferenceController extends BasePreferenceController {
public void updateState(Preference preference) { public void updateState(Preference preference) {
super.updateState(preference); super.updateState(preference);
setGearClickListenerForPreference(preference); setGearClickListenerForPreference(preference);
setActiveDreamIcon(preference);
} }
@Override @Override
@@ -78,4 +81,13 @@ public class CurrentDreamPreferenceController extends BasePreferenceController {
.filter((info) -> info.isActive) .filter((info) -> info.isActive)
.findFirst(); .findFirst();
} }
private void setActiveDreamIcon(Preference preference) {
if (!(preference instanceof GearPreference)) {
return;
}
final GearPreference gearPref = (GearPreference) preference;
gearPref.setIconSize(RestrictedPreference.ICON_SIZE_SMALL);
Utils.setSafeIcon(gearPref, mBackend.getActiveIcon());
}
} }

View File

@@ -96,15 +96,18 @@ public class MobileDataSlice implements CustomSliceable {
ListBuilder.ICON_IMAGE, title); ListBuilder.ICON_IMAGE, title);
final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction, final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
null /* actionTitle */, isMobileDataEnabled()); null /* actionTitle */, isMobileDataEnabled());
final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
.setTitle(title)
.addEndItem(toggleSliceAction)
.setPrimaryAction(primarySliceAction);
if (!Utils.isSettingsIntelligence(mContext)) {
rowBuilder.setSubtitle(summary);
}
final ListBuilder listBuilder = new ListBuilder(mContext, getUri(), final ListBuilder listBuilder = new ListBuilder(mContext, getUri(),
ListBuilder.INFINITY) ListBuilder.INFINITY)
.setAccentColor(color) .setAccentColor(color)
.addRow(new ListBuilder.RowBuilder() .addRow(rowBuilder);
.setTitle(title)
.setSubtitle(summary)
.addEndItem(toggleSliceAction)
.setPrimaryAction(primarySliceAction));
return listBuilder.build(); return listBuilder.build();
} }

View File

@@ -0,0 +1,154 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import static android.app.NotificationChannel.DEFAULT_ALLOW_BUBBLE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
import android.annotation.Nullable;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.content.Context;
import android.content.pm.ShortcutInfo;
import android.graphics.drawable.Drawable;
import android.service.notification.ConversationChannelWrapper;
import android.view.View;
import android.widget.ImageView;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settings.notification.app.AppConversationListPreferenceController;
import com.android.settingslib.RestrictedLockUtils;
import com.google.common.annotations.VisibleForTesting;
import java.util.List;
import java.util.stream.Collectors;
/**
* Displays a list of conversations that have either been selected or excluded from bubbling.
*/
public class AppBubbleListPreferenceController extends AppConversationListPreferenceController {
private static final String KEY = "bubble_conversations";
public AppBubbleListPreferenceController(Context context, NotificationBackend backend) {
super(context, backend);
}
@Override
public void onResume(NotificationBackend.AppRow appRow,
@Nullable NotificationChannel channel, @Nullable NotificationChannelGroup group,
Drawable conversationDrawable,
ShortcutInfo conversationInfo,
RestrictedLockUtils.EnforcedAdmin admin) {
super.onResume(appRow, channel, group, conversationDrawable, conversationInfo, admin);
// In case something changed in the foreground (e.g. via bubble button on notification)
loadConversationsAndPopulate();
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
if (!super.isAvailable()) {
return false;
}
if (mAppRow.bubblePreference == BUBBLE_PREFERENCE_NONE) {
return false;
}
return true;
}
@VisibleForTesting
@Override
public List<ConversationChannelWrapper> filterAndSortConversations(
List<ConversationChannelWrapper> conversations) {
return conversations.stream()
.sorted(mConversationComparator)
.filter((c) -> {
if (mAppRow.bubblePreference == BUBBLE_PREFERENCE_SELECTED) {
return c.getNotificationChannel().canBubble();
} else if (mAppRow.bubblePreference == BUBBLE_PREFERENCE_ALL) {
return c.getNotificationChannel().getAllowBubbles() == 0;
}
return false;
})
.collect(Collectors.toList());
}
@Override
protected int getTitleResId() {
// TODO: possible to left align like mocks?
return mAppRow.bubblePreference == BUBBLE_PREFERENCE_SELECTED
? R.string.bubble_app_setting_selected_conversation_title
: R.string.bubble_app_setting_excluded_conversation_title;
}
@VisibleForTesting
@Override
public Preference createConversationPref(final ConversationChannelWrapper conversation) {
final ConversationPreference pref = new ConversationPreference(mContext);
populateConversationPreference(conversation, pref);
pref.setOnClickListener((v) -> {
conversation.getNotificationChannel().setAllowBubbles(DEFAULT_ALLOW_BUBBLE);
mBackend.updateChannel(mAppRow.pkg, mAppRow.uid, conversation.getNotificationChannel());
mPreference.removePreference(pref);
if (mPreference.getPreferenceCount() == 0) {
mPreference.setVisible(false);
}
});
return pref;
}
/** Simple preference with a 'x' button at the end. */
@VisibleForTesting
public static class ConversationPreference extends Preference implements View.OnClickListener {
View.OnClickListener mOnClickListener;
ConversationPreference(Context context) {
super(context);
setWidgetLayoutResource(R.layout.bubble_conversation_remove_button);
}
@Override
public void onBindViewHolder(final PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
ImageView view = holder.itemView.findViewById(R.id.button);
view.setOnClickListener(mOnClickListener);
}
public void setOnClickListener(View.OnClickListener listener) {
mOnClickListener = listener;
}
@Override
public void onClick(View v) {
if (mOnClickListener != null) {
mOnClickListener.onClick(v);
}
}
}
}

View File

@@ -268,6 +268,15 @@ public class NotificationBackend {
} }
} }
public boolean hasSentMessage(String pkg, int uid) {
try {
return sINM.hasSentMessage(pkg, uid);
} catch (Exception e) {
Log.w(TAG, "Error calling NoMan", e);
return false;
}
}
/** /**
* Returns all notification channels associated with the package and uid that will bypass DND * Returns all notification channels associated with the package and uid that will bypass DND
*/ */

View File

@@ -22,6 +22,7 @@ import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.notification.AppBubbleListPreferenceController;
import com.android.settings.notification.NotificationBackend; import com.android.settings.notification.NotificationBackend;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
@@ -56,18 +57,20 @@ public class AppBubbleNotificationSettings extends NotificationSettings implemen
@Override @Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) { protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
mControllers = getPreferenceControllers(context, this); mControllers = getPreferenceControllers(context, this, mDependentFieldListener);
return new ArrayList<>(mControllers); return new ArrayList<>(mControllers);
} }
protected static List<NotificationPreferenceController> getPreferenceControllers( protected static List<NotificationPreferenceController> getPreferenceControllers(
Context context, AppBubbleNotificationSettings fragment) { Context context, AppBubbleNotificationSettings fragment,
DependentFieldListener listener) {
List<NotificationPreferenceController> controllers = new ArrayList<>(); List<NotificationPreferenceController> controllers = new ArrayList<>();
controllers.add(new HeaderPreferenceController(context, fragment)); controllers.add(new HeaderPreferenceController(context, fragment));
controllers.add(new BubblePreferenceController(context, fragment != null controllers.add(new BubblePreferenceController(context, fragment != null
? fragment.getChildFragmentManager() ? fragment.getChildFragmentManager()
: null, : null,
new NotificationBackend(), true /* isAppPage */)); new NotificationBackend(), true /* isAppPage */, listener));
controllers.add(new AppBubbleListPreferenceController(context, new NotificationBackend()));
return controllers; return controllers;
} }
@@ -114,7 +117,7 @@ public class AppBubbleNotificationSettings extends NotificationSettings implemen
public List<AbstractPreferenceController> createPreferenceControllers(Context public List<AbstractPreferenceController> createPreferenceControllers(Context
context) { context) {
return new ArrayList<>(AppBubbleNotificationSettings.getPreferenceControllers( return new ArrayList<>(AppBubbleNotificationSettings.getPreferenceControllers(
context, null)); context, null, null));
} }
}; };
} }

View File

@@ -19,6 +19,7 @@ package com.android.settings.notification.app;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutInfo;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
@@ -33,6 +34,7 @@ import com.android.settings.applications.AppInfoBase;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
import com.android.settings.notification.NotificationBackend; import com.android.settings.notification.NotificationBackend;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
@@ -42,8 +44,9 @@ public class AppConversationListPreferenceController extends NotificationPrefere
private static final String KEY = "conversations"; private static final String KEY = "conversations";
public static final String ARG_FROM_SETTINGS = "fromSettings"; public static final String ARG_FROM_SETTINGS = "fromSettings";
private List<ConversationChannelWrapper> mConversations; protected List<ConversationChannelWrapper> mConversations = new ArrayList<>();
private PreferenceCategory mPreference; protected PreferenceCategory mPreference;
private boolean mHasSentMsg;
public AppConversationListPreferenceController(Context context, NotificationBackend backend) { public AppConversationListPreferenceController(Context context, NotificationBackend backend) {
super(context, backend); super(context, backend);
@@ -74,12 +77,23 @@ public class AppConversationListPreferenceController extends NotificationPrefere
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
mPreference = (PreferenceCategory) preference; mPreference = (PreferenceCategory) preference;
loadConversationsAndPopulate();
}
protected void loadConversationsAndPopulate() {
if (mAppRow == null) {
return;
}
// Load channel settings // Load channel settings
new AsyncTask<Void, Void, Void>() { new AsyncTask<Void, Void, Void>() {
@Override @Override
protected Void doInBackground(Void... unused) { protected Void doInBackground(Void... unused) {
mConversations = mBackend.getConversations(mAppRow.pkg, mAppRow.uid).getList(); mHasSentMsg = mBackend.hasSentMessage(mAppRow.pkg, mAppRow.uid);
Collections.sort(mConversations, mConversationComparator); ParceledListSlice<ConversationChannelWrapper> list =
mBackend.getConversations(mAppRow.pkg, mAppRow.uid);
if (list != null) {
mConversations = filterAndSortConversations(list.getList());
}
return null; return null;
} }
@@ -93,15 +107,35 @@ public class AppConversationListPreferenceController extends NotificationPrefere
}.execute(); }.execute();
} }
protected List<ConversationChannelWrapper> filterAndSortConversations(
List<ConversationChannelWrapper> conversations) {
Collections.sort(conversations, mConversationComparator);
return conversations;
}
protected int getTitleResId() {
return R.string.conversations_category_title;
}
private void populateList() { private void populateList() {
if (mPreference == null) {
return;
}
// TODO: if preference has children, compare with newly loaded list // TODO: if preference has children, compare with newly loaded list
mPreference.removeAll(); mPreference.removeAll();
mPreference.setTitle(R.string.conversations_category_title);
if (mConversations.isEmpty()) { if (mConversations.isEmpty()) {
mPreference.setVisible(false); if (mHasSentMsg) {
mPreference.setVisible(true);
Preference notSupportedPref = new Preference(mContext);
notSupportedPref.setSummary(mContext.getString(
R.string.convo_not_supported_summary, mAppRow.label));
mPreference.addPreference(notSupportedPref);
} else {
mPreference.setVisible(false);
}
} else { } else {
mPreference.setVisible(true); mPreference.setVisible(true);
mPreference.setTitle(getTitleResId());
populateConversations(); populateConversations();
} }
} }
@@ -117,6 +151,12 @@ public class AppConversationListPreferenceController extends NotificationPrefere
protected Preference createConversationPref(final ConversationChannelWrapper conversation) { protected Preference createConversationPref(final ConversationChannelWrapper conversation) {
Preference pref = new Preference(mContext); Preference pref = new Preference(mContext);
populateConversationPreference(conversation, pref);
return pref;
}
protected void populateConversationPreference(final ConversationChannelWrapper conversation,
final Preference pref) {
ShortcutInfo si = conversation.getShortcutInfo(); ShortcutInfo si = conversation.getShortcutInfo();
pref.setTitle(si != null pref.setTitle(si != null
@@ -147,7 +187,6 @@ public class AppConversationListPreferenceController extends NotificationPrefere
.setTitleText(pref.getTitle()) .setTitleText(pref.getTitle())
.setSourceMetricsCategory(SettingsEnums.NOTIFICATION_APP_NOTIFICATION) .setSourceMetricsCategory(SettingsEnums.NOTIFICATION_APP_NOTIFICATION)
.toIntent()); .toIntent());
return pref;
} }
protected Comparator<ConversationChannelWrapper> mConversationComparator = protected Comparator<ConversationChannelWrapper> mConversationComparator =

View File

@@ -52,6 +52,8 @@ public class BubblePreference extends Preference implements View.OnClickListener
private ButtonViewHolder mBubbleSelectedButton; private ButtonViewHolder mBubbleSelectedButton;
private ButtonViewHolder mBubbleNoneButton; private ButtonViewHolder mBubbleNoneButton;
private boolean mSelectedVisible;
public BubblePreference(Context context) { public BubblePreference(Context context) {
this(context, null); this(context, null);
} }
@@ -89,6 +91,11 @@ public class BubblePreference extends Preference implements View.OnClickListener
} }
} }
public void setSelectedVisibility(boolean visible) {
mSelectedVisible = visible;
notifyChanged();
}
@Override @Override
public void onBindViewHolder(final PreferenceViewHolder holder) { public void onBindViewHolder(final PreferenceViewHolder holder) {
super.onBindViewHolder(holder); super.onBindViewHolder(holder);
@@ -122,7 +129,8 @@ public class BubblePreference extends Preference implements View.OnClickListener
mSelectedPreference == BUBBLE_PREFERENCE_SELECTED); mSelectedPreference == BUBBLE_PREFERENCE_SELECTED);
bubbleSelected.setTag(BUBBLE_PREFERENCE_SELECTED); bubbleSelected.setTag(BUBBLE_PREFERENCE_SELECTED);
bubbleSelected.setOnClickListener(this); bubbleSelected.setOnClickListener(this);
bubbleSelected.setVisibility(disabledByAdmin ? View.GONE : View.VISIBLE); bubbleSelected.setVisibility((!mSelectedVisible || disabledByAdmin)
? View.GONE : View.VISIBLE);
View bubbleNone = holder.findViewById(R.id.bubble_none); View bubbleNone = holder.findViewById(R.id.bubble_none);
ImageView bubbleNoneImage = (ImageView) holder.findViewById(R.id.bubble_none_icon); ImageView bubbleNoneImage = (ImageView) holder.findViewById(R.id.bubble_none_icon);

View File

@@ -47,12 +47,17 @@ public class BubblePreferenceController extends NotificationPreferenceController
private FragmentManager mFragmentManager; private FragmentManager mFragmentManager;
private boolean mIsAppPage; private boolean mIsAppPage;
private boolean mHasSentInvalidMsg;
private int mNumConversations;
private NotificationSettings.DependentFieldListener mListener;
public BubblePreferenceController(Context context, @Nullable FragmentManager fragmentManager, public BubblePreferenceController(Context context, @Nullable FragmentManager fragmentManager,
NotificationBackend backend, boolean isAppPage) { NotificationBackend backend, boolean isAppPage,
@Nullable NotificationSettings.DependentFieldListener listener) {
super(context, backend); super(context, backend);
mFragmentManager = fragmentManager; mFragmentManager = fragmentManager;
mIsAppPage = isAppPage; mIsAppPage = isAppPage;
mListener = listener;
} }
@Override @Override
@@ -81,10 +86,14 @@ public class BubblePreferenceController extends NotificationPreferenceController
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
if (mIsAppPage && mAppRow != null) { if (mIsAppPage && mAppRow != null) {
mHasSentInvalidMsg = mBackend.hasSentMessage(mAppRow.pkg, mAppRow.uid);
mNumConversations = mBackend.getConversations(
mAppRow.pkg, mAppRow.uid).getList().size();
// We're on the app specific bubble page which displays a tri-state // We're on the app specific bubble page which displays a tri-state
int backEndPref = mAppRow.bubblePreference; int backEndPref = mAppRow.bubblePreference;
BubblePreference pref = (BubblePreference) preference; BubblePreference pref = (BubblePreference) preference;
pref.setDisabledByAdmin(mAdmin); pref.setDisabledByAdmin(mAdmin);
pref.setSelectedVisibility(!mHasSentInvalidMsg || mNumConversations > 0);
if (!isGloballyEnabled()) { if (!isGloballyEnabled()) {
pref.setSelectedPreference(BUBBLE_PREFERENCE_NONE); pref.setSelectedPreference(BUBBLE_PREFERENCE_NONE);
} else { } else {
@@ -122,6 +131,9 @@ public class BubblePreferenceController extends NotificationPreferenceController
mBackend.setAllowBubbles(mAppRow.pkg, mAppRow.uid, value); mBackend.setAllowBubbles(mAppRow.pkg, mAppRow.uid, value);
} }
} }
if (mListener != null) {
mListener.onFieldValueChanged();
}
} }
return true; return true;
} }

View File

@@ -92,7 +92,7 @@ public class ConversationNotificationSettings extends NotificationSettings {
mControllers.add(new BadgePreferenceController(context, mBackend)); mControllers.add(new BadgePreferenceController(context, mBackend));
mControllers.add(new NotificationsOffPreferenceController(context)); mControllers.add(new NotificationsOffPreferenceController(context));
mControllers.add(new BubblePreferenceController(context, getChildFragmentManager(), mControllers.add(new BubblePreferenceController(context, getChildFragmentManager(),
mBackend, false /* isAppPage */)); mBackend, false /* isAppPage */, null /* dependentFieldListener */));
mControllers.add(new ConversationDemotePreferenceController(context, this, mBackend)); mControllers.add(new ConversationDemotePreferenceController(context, this, mBackend));
mControllers.add(new BubbleCategoryPreferenceController(context)); mControllers.add(new BubbleCategoryPreferenceController(context));
mControllers.add(new BubbleLinkPreferenceController(context)); mControllers.add(new BubbleLinkPreferenceController(context));

View File

@@ -287,13 +287,13 @@ public class ZenModeBackend {
protected int getAlarmsTotalSilencePeopleSummary(int category) { protected int getAlarmsTotalSilencePeopleSummary(int category) {
if (category == NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) { if (category == NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) {
return R.string.zen_mode_from_none; return R.string.zen_mode_none_messages;
} else if (category == NotificationManager.Policy.PRIORITY_CATEGORY_CALLS){ } else if (category == NotificationManager.Policy.PRIORITY_CATEGORY_CALLS){
return R.string.zen_mode_from_none; return R.string.zen_mode_none_calls;
} else if (category == NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS) { } else if (category == NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS) {
return R.string.zen_mode_from_no_conversations; return R.string.zen_mode_from_no_conversations;
} }
return R.string.zen_mode_from_none; return R.string.zen_mode_from_no_conversations;
} }
protected int getConversationSummary() { protected int getConversationSummary() {
@@ -322,7 +322,7 @@ public class ZenModeBackend {
return R.string.zen_mode_from_starred; return R.string.zen_mode_from_starred;
case ZenPolicy.PEOPLE_TYPE_NONE: case ZenPolicy.PEOPLE_TYPE_NONE:
default: default:
return R.string.zen_mode_from_none; return R.string.zen_mode_none_calls;
} }
} }
@@ -337,7 +337,7 @@ public class ZenModeBackend {
return R.string.zen_mode_from_starred; return R.string.zen_mode_from_starred;
case ZenPolicy.PEOPLE_TYPE_NONE: case ZenPolicy.PEOPLE_TYPE_NONE:
default: default:
return R.string.zen_mode_from_none; return R.string.zen_mode_none_messages;
} }
} }
@@ -472,7 +472,7 @@ public class ZenModeBackend {
List<String> displayContacts = new ArrayList<>(); List<String> displayContacts = new ArrayList<>();
if (numStarredContacts == 0) { if (numStarredContacts == 0) {
displayContacts.add(context.getString(R.string.zen_mode_from_none)); displayContacts.add(context.getString(R.string.zen_mode_starred_contacts_summary_none));
} else { } else {
for (int i = 0; i < 2 && i < numStarredContacts; i++) { for (int i = 0; i < 2 && i < numStarredContacts; i++) {
displayContacts.add(starredContacts.get(i)); displayContacts.add(starredContacts.get(i));
@@ -494,10 +494,11 @@ public class ZenModeBackend {
String getContactsNumberSummary(Context context) { String getContactsNumberSummary(Context context) {
final int numContacts = queryAllContactsData().getCount(); final int numContacts = queryAllContactsData().getCount();
if (numContacts == 0) { if (numContacts == 0) {
return context.getResources().getString(R.string.zen_mode_from_none); return context.getResources().getString(
R.string.zen_mode_contacts_count_none);
} }
return context.getResources().getString(R.string.zen_mode_contacts_senders_summary, return context.getResources().getQuantityString(R.plurals.zen_mode_contacts_count,
numContacts); numContacts, numContacts);
} }
private Cursor queryStarredContactsData() { private Cursor queryStarredContactsData() {

View File

@@ -91,7 +91,9 @@ public class ZenModePrioritySendersPreferenceController
makeRadioPreference(KEY_ANY, makeRadioPreference(KEY_ANY,
com.android.settings.R.string.zen_mode_from_anyone); com.android.settings.R.string.zen_mode_from_anyone);
makeRadioPreference(KEY_NONE, makeRadioPreference(KEY_NONE,
com.android.settings.R.string.zen_mode_from_none); mIsMessages
? com.android.settings.R.string.zen_mode_none_messages
: com.android.settings.R.string.zen_mode_none_calls);
updateSummaries(); updateSummaries();
} }

View File

@@ -91,7 +91,10 @@ public class ZenModeSendersImagePreferenceController
newImageRes = mIsMessages newImageRes = mIsMessages
? R.drawable.zen_messages_none ? R.drawable.zen_messages_none
: R.drawable.zen_calls_none; : R.drawable.zen_calls_none;
newContentDescription = mContext.getString(R.string.zen_mode_from_none); newContentDescription =
mContext.getString(mIsMessages
? R.string.zen_mode_none_messages
: R.string.zen_mode_none_calls);
} }
mImageView.setImageResource(newImageRes); mImageView.setImageResource(newImageRes);

View File

@@ -156,7 +156,7 @@ public class ZenModeSettings extends ZenModeSettingsBase {
|| PRIORITY_CATEGORY_REPEAT_CALLERS == category, true); || PRIORITY_CATEGORY_REPEAT_CALLERS == category, true);
int numCategories = enabledCategories.size(); int numCategories = enabledCategories.size();
if (numCategories == 0) { if (numCategories == 0) {
return mContext.getString(R.string.zen_mode_from_none); return mContext.getString(R.string.zen_mode_none_calls);
} else if (numCategories == 1) { } else if (numCategories == 1) {
return mContext.getString(R.string.zen_mode_calls_summary_one, return mContext.getString(R.string.zen_mode_calls_summary_one,
enabledCategories.get(0)); enabledCategories.get(0));
@@ -172,7 +172,7 @@ public class ZenModeSettings extends ZenModeSettingsBase {
category -> PRIORITY_CATEGORY_MESSAGES == category, false); category -> PRIORITY_CATEGORY_MESSAGES == category, false);
int numCategories = enabledCategories.size(); int numCategories = enabledCategories.size();
if (numCategories == 0) { if (numCategories == 0) {
return mContext.getString(R.string.zen_mode_from_none); return mContext.getString(R.string.zen_mode_none_messages);
} else { } else {
return enabledCategories.get(0); return enabledCategories.get(0);
} }

View File

@@ -82,15 +82,18 @@ public class ZenModeSliceBuilder {
final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction, final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
null /* actionTitle */, null /* actionTitle */,
isZenModeEnabled); isZenModeEnabled);
final RowBuilder rowBuilder = new RowBuilder()
.setTitle(title)
.addEndItem(toggleSliceAction)
.setPrimaryAction(primarySliceAction);
if (!Utils.isSettingsIntelligence(context)) {
rowBuilder.setSubtitle(subtitle);
}
return new ListBuilder(context, CustomSliceRegistry.ZEN_MODE_SLICE_URI, return new ListBuilder(context, CustomSliceRegistry.ZEN_MODE_SLICE_URI,
ListBuilder.INFINITY) ListBuilder.INFINITY)
.setAccentColor(color) .setAccentColor(color)
.addRow(new RowBuilder() .addRow(rowBuilder)
.setTitle(title)
.setSubtitle(subtitle)
.addEndItem(toggleSliceAction)
.setPrimaryAction(primarySliceAction))
.build(); .build();
} }

View File

@@ -241,16 +241,19 @@ public class SliceBuilderUtils {
final SliceAction sliceAction = getToggleAction(context, sliceData, final SliceAction sliceAction = getToggleAction(context, sliceData,
toggleController.isChecked()); toggleController.isChecked());
final Set<String> keywords = buildSliceKeywords(sliceData); final Set<String> keywords = buildSliceKeywords(sliceData);
final RowBuilder rowBuilder = new RowBuilder()
.setTitle(sliceData.getTitle())
.setPrimaryAction(
SliceAction.createDeeplink(contentIntent, icon,
ListBuilder.ICON_IMAGE, sliceData.getTitle()))
.addEndItem(sliceAction);
if (!Utils.isSettingsIntelligence(context)) {
rowBuilder.setSubtitle(subtitleText);
}
return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY) return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
.setAccentColor(color) .setAccentColor(color)
.addRow(new RowBuilder() .addRow(rowBuilder)
.setTitle(sliceData.getTitle())
.setSubtitle(subtitleText)
.setPrimaryAction(
SliceAction.createDeeplink(contentIntent, icon,
ListBuilder.ICON_IMAGE, sliceData.getTitle()))
.addEndItem(sliceAction))
.setKeywords(keywords) .setKeywords(keywords)
.build(); .build();
} }
@@ -262,16 +265,19 @@ public class SliceBuilderUtils {
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData); final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
@ColorInt final int color = Utils.getColorAccentDefaultColor(context); @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
final Set<String> keywords = buildSliceKeywords(sliceData); final Set<String> keywords = buildSliceKeywords(sliceData);
final RowBuilder rowBuilder = new RowBuilder()
.setTitle(sliceData.getTitle())
.setPrimaryAction(
SliceAction.createDeeplink(contentIntent, icon,
ListBuilder.ICON_IMAGE,
sliceData.getTitle()));
if (!Utils.isSettingsIntelligence(context)) {
rowBuilder.setSubtitle(subtitleText);
}
return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY) return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
.setAccentColor(color) .setAccentColor(color)
.addRow(new RowBuilder() .addRow(rowBuilder)
.setTitle(sliceData.getTitle())
.setSubtitle(subtitleText)
.setPrimaryAction(
SliceAction.createDeeplink(contentIntent, icon,
ListBuilder.ICON_IMAGE,
sliceData.getTitle())))
.setKeywords(keywords) .setKeywords(keywords)
.build(); .build();
} }
@@ -301,7 +307,6 @@ public class SliceBuilderUtils {
} }
final InputRangeBuilder inputRangeBuilder = new InputRangeBuilder() final InputRangeBuilder inputRangeBuilder = new InputRangeBuilder()
.setTitle(sliceData.getTitle()) .setTitle(sliceData.getTitle())
.setSubtitle(subtitleText)
.setPrimaryAction(primaryAction) .setPrimaryAction(primaryAction)
.setMax(sliderController.getMax()) .setMax(sliderController.getMax())
.setMin(sliderController.getMin()) .setMin(sliderController.getMin())
@@ -311,6 +316,9 @@ public class SliceBuilderUtils {
inputRangeBuilder.setTitleItem(icon, ListBuilder.ICON_IMAGE); inputRangeBuilder.setTitleItem(icon, ListBuilder.ICON_IMAGE);
color = CustomSliceable.COLOR_NOT_TINTED; color = CustomSliceable.COLOR_NOT_TINTED;
} }
if (!Utils.isSettingsIntelligence(context)) {
inputRangeBuilder.setSubtitle(subtitleText);
}
return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY) return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
.setAccentColor(color) .setAccentColor(color)
@@ -330,14 +338,17 @@ public class SliceBuilderUtils {
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData); final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
@ColorInt final int color = Utils.getColorAccentDefaultColor(context); @ColorInt final int color = Utils.getColorAccentDefaultColor(context);
final Set<String> keywords = buildSliceKeywords(sliceData); final Set<String> keywords = buildSliceKeywords(sliceData);
final RowBuilder rowBuilder = new RowBuilder()
.setTitle(sliceData.getTitle())
.setPrimaryAction(primaryAction)
.addEndItem(copyableAction);
if (!Utils.isSettingsIntelligence(context)) {
rowBuilder.setSubtitle(subtitleText);
}
return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY) return new ListBuilder(context, sliceData.getUri(), ListBuilder.INFINITY)
.setAccentColor(color) .setAccentColor(color)
.addRow(new RowBuilder() .addRow(rowBuilder)
.setTitle(sliceData.getTitle())
.setSubtitle(subtitleText)
.setPrimaryAction(primaryAction)
.addEndItem(copyableAction))
.setKeywords(keywords) .setKeywords(keywords)
.build(); .build();
} }
@@ -418,14 +429,17 @@ public class SliceBuilderUtils {
final SliceAction primaryAction = SliceAction.createDeeplink( final SliceAction primaryAction = SliceAction.createDeeplink(
getContentPendingIntent(context, data), getContentPendingIntent(context, data),
icon, ListBuilder.ICON_IMAGE, title); icon, ListBuilder.ICON_IMAGE, title);
final RowBuilder rowBuilder = new RowBuilder()
.setTitle(title)
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
.setPrimaryAction(primaryAction);
if (!Utils.isSettingsIntelligence(context)) {
rowBuilder.setSubtitle(subtitle);
}
return new ListBuilder(context, data.getUri(), ListBuilder.INFINITY) return new ListBuilder(context, data.getUri(), ListBuilder.INFINITY)
.setAccentColor(color) .setAccentColor(color)
.addRow(new RowBuilder() .addRow(rowBuilder)
.setTitle(title)
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
.setSubtitle(subtitle)
.setPrimaryAction(primaryAction))
.setKeywords(keywords) .setKeywords(keywords)
.build(); .build();
} }

View File

@@ -544,14 +544,9 @@ public class WifiSettings2 extends RestrictedSettingsFragment
final WifiEntry selectedEntry = final WifiEntry selectedEntry =
((LongPressWifiEntryPreference) preference).getWifiEntry(); ((LongPressWifiEntryPreference) preference).getWifiEntry();
// If the clicked WiFi entry is never connected, launch Wi-Fi edit UI to edit password. if (selectedEntry.shouldEditBeforeConnect()) {
if (selectedEntry.getSecurity() != WifiEntry.SECURITY_NONE launchConfigNewNetworkFragment(selectedEntry);
&& selectedEntry.getSecurity() != WifiEntry.SECURITY_OWE) { return true;
final WifiConfiguration config = selectedEntry.getWifiConfiguration();
if (config != null && !config.getNetworkSelectionStatus().hasEverConnected()) {
launchConfigNewNetworkFragment(selectedEntry);
return true;
}
} }
connect(selectedEntry, true /* editIfNoConfig */, true /* fullScreenEdit */); connect(selectedEntry, true /* editIfNoConfig */, true /* fullScreenEdit */);

View File

@@ -269,14 +269,17 @@ public class WifiCallingSliceHelper {
// Top row shows information on current preference state // Top row shows information on current preference state
final ListBuilder listBuilder = new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY) final ListBuilder listBuilder = new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext)); .setAccentColor(Utils.getColorAccentDefaultColor(mContext));
listBuilder.setHeader(new ListBuilder.HeaderBuilder() final ListBuilder.HeaderBuilder headerBuilder = new ListBuilder.HeaderBuilder()
.setTitle(res.getText(R.string.wifi_calling_mode_title)) .setTitle(res.getText(R.string.wifi_calling_mode_title))
.setSubtitle(getWifiCallingPreferenceSummary(currentWfcPref, subId))
.setPrimaryAction(SliceAction.createDeeplink( .setPrimaryAction(SliceAction.createDeeplink(
getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY), getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY),
icon, icon,
ListBuilder.ICON_IMAGE, ListBuilder.ICON_IMAGE,
res.getText(R.string.wifi_calling_mode_title)))); res.getText(R.string.wifi_calling_mode_title)));
if (!Utils.isSettingsIntelligence(mContext)) {
headerBuilder.setSubtitle(getWifiCallingPreferenceSummary(currentWfcPref, subId));
}
listBuilder.setHeader(headerBuilder);
if (isWifiOnlySupported) { if (isWifiOnlySupported) {
listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder, listBuilder.addRow(wifiPreferenceRowBuilder(listBuilder,
@@ -458,14 +461,17 @@ public class WifiCallingSliceHelper {
private Slice getNonActionableWifiCallingSlice(CharSequence title, CharSequence subtitle, private Slice getNonActionableWifiCallingSlice(CharSequence title, CharSequence subtitle,
Uri sliceUri, PendingIntent primaryActionIntent) { Uri sliceUri, PendingIntent primaryActionIntent) {
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal); final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal);
final RowBuilder rowBuilder = new RowBuilder()
.setTitle(title)
.setPrimaryAction(SliceAction.createDeeplink(
primaryActionIntent, icon, ListBuilder.SMALL_IMAGE,
title));
if (!Utils.isSettingsIntelligence(mContext)) {
rowBuilder.setSubtitle(subtitle);
}
return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY) return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext)) .setAccentColor(Utils.getColorAccentDefaultColor(mContext))
.addRow(new RowBuilder() .addRow(rowBuilder)
.setTitle(title)
.setSubtitle(subtitle)
.setPrimaryAction(SliceAction.createDeeplink(
primaryActionIntent, icon, ListBuilder.SMALL_IMAGE,
title)))
.build(); .build();
} }

View File

@@ -29,7 +29,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.ActionBar; import android.app.ActionBar;
import android.app.Activity;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
@@ -67,6 +66,7 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric; import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowBinder;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.ArrayList; import java.util.ArrayList;
@@ -281,4 +281,22 @@ public class UtilsTest {
assertThat(actionBar.getElevation()).isEqualTo(0.f); assertThat(actionBar.getElevation()).isEqualTo(0.f);
} }
@Test
public void isSettingsIntelligence_IsSI_returnTrue() {
final String siPackageName = mContext.getString(
R.string.config_settingsintelligence_package_name);
ShadowBinder.setCallingUid(USER_ID);
when(mPackageManager.getPackagesForUid(USER_ID)).thenReturn(new String[]{siPackageName});
assertThat(Utils.isSettingsIntelligence(mContext)).isTrue();
}
@Test
public void isSettingsIntelligence_IsNotSI_returnFalse() {
ShadowBinder.setCallingUid(USER_ID);
when(mPackageManager.getPackagesForUid(USER_ID)).thenReturn(new String[]{PACKAGE_NAME});
assertThat(Utils.isSettingsIntelligence(mContext)).isFalse();
}
} }

View File

@@ -130,8 +130,8 @@ public class AccessibilitySettingsTest {
} }
@Test @Test
public void getServiceSummary_invisibleType_shortcutDisabled_showsOffSummary() { public void getServiceSummary_invisibleToggle_shortcutDisabled_showsOffSummary() {
setInvisibleFragmentType(mServiceInfo); setInvisibleToggleFragmentType(mServiceInfo);
doReturn(DEFAULT_SUMMARY).when(mServiceInfo).loadSummary(any()); doReturn(DEFAULT_SUMMARY).when(mServiceInfo).loadSummary(any());
final CharSequence summary = AccessibilitySettings.getServiceSummary(mContext, final CharSequence summary = AccessibilitySettings.getServiceSummary(mContext,
@@ -277,7 +277,7 @@ public class AccessibilitySettingsTest {
when(mockInfo.getComponentName()).thenReturn(DUMMY_COMPONENT_NAME); when(mockInfo.getComponentName()).thenReturn(DUMMY_COMPONENT_NAME);
} }
private void setInvisibleFragmentType(AccessibilityServiceInfo info) { private void setInvisibleToggleFragmentType(AccessibilityServiceInfo info) {
info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.R; info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON; info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
} }

View File

@@ -102,36 +102,36 @@ public final class AccessibilityUtilTest {
} }
@Test @Test
public void getAccessibilityServiceFragmentType_targetSdkQ_legacyType() { public void getAccessibilityServiceFragmentType_targetSdkQ_volumeShortcutType() {
final AccessibilityServiceInfo info = getMockAccessibilityServiceInfo(); final AccessibilityServiceInfo info = getMockAccessibilityServiceInfo();
info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON; info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
assertThat(AccessibilityUtil.getAccessibilityServiceFragmentType(info)).isEqualTo( assertThat(AccessibilityUtil.getAccessibilityServiceFragmentType(info)).isEqualTo(
AccessibilityUtil.AccessibilityServiceFragmentType.LEGACY); AccessibilityUtil.AccessibilityServiceFragmentType.VOLUME_SHORTCUT_TOGGLE);
} }
@Test @Test
public void getAccessibilityServiceFragmentType_targetSdkR_HaveA11yButton_headlessType() { public void getAccessibilityServiceFragmentType_targetSdkR_HaveA11yButton_invisibleType() {
final AccessibilityServiceInfo info = getMockAccessibilityServiceInfo(); final AccessibilityServiceInfo info = getMockAccessibilityServiceInfo();
info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.R; info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON; info.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
assertThat(AccessibilityUtil.getAccessibilityServiceFragmentType(info)).isEqualTo( assertThat(AccessibilityUtil.getAccessibilityServiceFragmentType(info)).isEqualTo(
AccessibilityUtil.AccessibilityServiceFragmentType.INVISIBLE); AccessibilityUtil.AccessibilityServiceFragmentType.INVISIBLE_TOGGLE);
} }
@Test @Test
public void getAccessibilityServiceFragmentType_targetSdkR_NoA11yButton_intuitiveType() { public void getAccessibilityServiceFragmentType_targetSdkR_NoA11yButton_toggleType() {
final AccessibilityServiceInfo info = getMockAccessibilityServiceInfo(); final AccessibilityServiceInfo info = getMockAccessibilityServiceInfo();
info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.R; info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
info.flags |= ~AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON; info.flags |= ~AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
assertThat(AccessibilityUtil.getAccessibilityServiceFragmentType(info)).isEqualTo( assertThat(AccessibilityUtil.getAccessibilityServiceFragmentType(info)).isEqualTo(
AccessibilityUtil.AccessibilityServiceFragmentType.INTUITIVE); AccessibilityUtil.AccessibilityServiceFragmentType.TOGGLE);
} }
@Test @Test

View File

@@ -0,0 +1,173 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification.app;
import static android.app.NotificationChannel.DEFAULT_ALLOW_BUBBLE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutInfo;
import android.os.UserManager;
import android.service.notification.ConversationChannelWrapper;
import androidx.preference.PreferenceCategory;
import com.android.settings.notification.AppBubbleListPreferenceController;
import com.android.settings.notification.NotificationBackend;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class AppBubbleListPreferenceControllerTest {
private Context mContext;
@Mock
private NotificationBackend mBackend;
@Mock
private NotificationManager mNm;
@Mock
private UserManager mUm;
private AppBubbleListPreferenceController mController;
private ParceledListSlice<ConversationChannelWrapper> mConvoList;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
mContext = RuntimeEnvironment.application;
List<ConversationChannelWrapper> convoList = new ArrayList<>();
convoList.add(getConvo(-1, "default"));
convoList.add(getConvo(1, "selected"));
convoList.add(getConvo(0, "excluded"));
mConvoList = new ParceledListSlice<>(convoList);
when(mBackend.getConversations(anyString(), anyInt())).thenReturn(mConvoList);
mController = new AppBubbleListPreferenceController(mContext, mBackend);
}
ConversationChannelWrapper getConvo(int bubbleChannelPref, String channelId) {
ConversationChannelWrapper ccw = new ConversationChannelWrapper();
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn(channelId);
when(channel.getAllowBubbles()).thenReturn(bubbleChannelPref);
when(channel.canBubble()).thenReturn(bubbleChannelPref == 1);
ccw.setNotificationChannel(channel);
ccw.setPkg("pkg");
ccw.setUid(1);
ccw.setShortcutInfo(mock(ShortcutInfo.class));
return ccw;
}
@Test
public void isAvailable_BUBBLE_PREFERENCE_NONE_false() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_NONE;
mController.onResume(appRow, null, null, null, null, null);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_BUBBLE_PREFERENCE_SELECTED_true() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED;
mController.onResume(appRow, null, null, null, null, null);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_BUBBLE_PREFERENCE_ALL_true() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
mController.onResume(appRow, null, null, null, null, null);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void filterAndSortConversations_BUBBLE_PREFERENCE_SELECTED_filtersAllowedBubbles() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED;
mController.onResume(appRow, null, null, null, null, null);
List<ConversationChannelWrapper> result =
mController.filterAndSortConversations(mConvoList.getList());
assertThat(result.size()).isEqualTo(1);
assertThat(result.get(0).getNotificationChannel().getId())
.isEqualTo("selected");
}
@Test
public void filterAndSortConversations_BUBBLE_PREFERENCE_ALL_filtersExcludedBubbles() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
mController.onResume(appRow, null, null, null, null, null);
List<ConversationChannelWrapper> result =
mController.filterAndSortConversations(mConvoList.getList());
assertThat(result.size()).isEqualTo(1);
assertThat(result.get(0).getNotificationChannel().getId())
.isEqualTo("excluded");
}
@Test
public void clickConversationPref_updatesChannel() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
appRow.pkg = "PKG";
mController.onResume(appRow, null, null, null, null, null);
mController.mPreference = new PreferenceCategory(mContext);
ConversationChannelWrapper ccw = mConvoList.getList().get(0);
AppBubbleListPreferenceController.ConversationPreference pref =
(AppBubbleListPreferenceController.ConversationPreference)
mController.createConversationPref(ccw);
pref.onClick(null);
verify(ccw.getNotificationChannel()).setAllowBubbles(DEFAULT_ALLOW_BUBBLE);
verify(mBackend).updateChannel(anyString(), anyInt(), any(NotificationChannel.class));
}
}

View File

@@ -80,6 +80,8 @@ public class BubblePreferenceControllerTest {
private PreferenceScreen mScreen; private PreferenceScreen mScreen;
@Mock @Mock
private FragmentManager mFragmentManager; private FragmentManager mFragmentManager;
@Mock
private NotificationSettings.DependentFieldListener mListener;
private BubblePreferenceController mController; private BubblePreferenceController mController;
private BubblePreferenceController mAppPageController; private BubblePreferenceController mAppPageController;
@@ -93,9 +95,9 @@ public class BubblePreferenceControllerTest {
mContext = RuntimeEnvironment.application; mContext = RuntimeEnvironment.application;
when(mFragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class)); when(mFragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class));
mController = spy(new BubblePreferenceController(mContext, mFragmentManager, mBackend, mController = spy(new BubblePreferenceController(mContext, mFragmentManager, mBackend,
false /* isAppPage */)); false /* isAppPage */, mListener));
mAppPageController = spy(new BubblePreferenceController(mContext, mFragmentManager, mAppPageController = spy(new BubblePreferenceController(mContext, mFragmentManager,
mBackend, true /* isAppPage */)); mBackend, true /* isAppPage */, mListener));
} }
@Test @Test
@@ -106,7 +108,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testIsAvailable_notIfAppBlocked() { public void isAvailable_notIfAppBlocked() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.banned = true; appRow.banned = true;
@@ -115,7 +117,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testIsAvailable_notIfChannelBlocked() { public void isAvailable_notIfChannelBlocked() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
@@ -125,7 +127,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testIsAvailable_channel_yesIfAppOff() { public void isAvailable_channel_yesIfAppOff() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_NONE; appRow.bubblePreference = BUBBLE_PREFERENCE_NONE;
@@ -137,7 +139,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testIsNotAvailable_ifOffGlobally_app() { public void isNotAvailable_ifOffGlobally_app() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
mController.onResume(appRow, null, null, null, null, null); mController.onResume(appRow, null, null, null, null, null);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.putInt(mContext.getContentResolver(),
@@ -147,7 +149,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testIsAvailable_notIfOffGlobally_channel() { public void isAvailable_notIfOffGlobally_channel() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
@@ -159,7 +161,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testIsAvailable_app_evenIfOffGlobally() { public void isAvailable_app_evenIfOffGlobally() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
mAppPageController.onResume(appRow, null, null, null, null, null); mAppPageController.onResume(appRow, null, null, null, null, null);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.putInt(mContext.getContentResolver(),
@@ -169,7 +171,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testIsAvailable_app() { public void isAvailable_app() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
mController.onResume(appRow, null, null, null, null, null); mController.onResume(appRow, null, null, null, null, null);
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
@@ -178,7 +180,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testIsAvailable_defaultChannel() { public void isAvailable_defaultChannel() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_ALL; appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
@@ -191,7 +193,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testIsAvailable_channel() { public void isAvailable_channel() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_ALL; appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
@@ -203,7 +205,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testUpdateState_disabledByAdmin() { public void updateState_disabledByAdmin() {
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn("something"); when(channel.getId()).thenReturn("something");
mController.onResume(new NotificationBackend.AppRow(), channel, null, mController.onResume(new NotificationBackend.AppRow(), channel, null,
@@ -216,7 +218,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testUpdateState_app_disabledByAdmin() { public void updateState_app_disabledByAdmin() {
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn("something"); when(channel.getId()).thenReturn("something");
mAppPageController.onResume(new NotificationBackend.AppRow(), channel, null, mAppPageController.onResume(new NotificationBackend.AppRow(), channel, null,
@@ -229,7 +231,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testUpdateState_channel_channelNotBlockable() { public void updateState_channel_channelNotBlockable() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
@@ -243,7 +245,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testUpdateState_channel() { public void updateState_channel() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class); NotificationChannel channel = mock(NotificationChannel.class);
@@ -263,7 +265,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testUpdateState_app() { public void updateState_app() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.label = "App!"; appRow.label = "App!";
@@ -288,7 +290,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testUpdateState_app_offGlobally() { public void updateState_app_offGlobally() {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.putInt(mContext.getContentResolver(),
NOTIFICATION_BUBBLES, SYSTEM_WIDE_OFF); NOTIFICATION_BUBBLES, SYSTEM_WIDE_OFF);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
@@ -302,7 +304,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testOnPreferenceChange_on_channel() { public void onPreferenceChange_on_channel() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED; appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED;
@@ -321,7 +323,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testOnPreferenceChange_off_channel() { public void onPreferenceChange_off_channel() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED; appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED;
@@ -341,7 +343,7 @@ public class BubblePreferenceControllerTest {
@Test @Test
public void testOnPreferenceChange_app_all() { public void onPreferenceChange_app_all() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_NONE; appRow.bubblePreference = BUBBLE_PREFERENCE_NONE;
@@ -379,7 +381,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testOnPreferenceChange_app_selected() { public void onPreferenceChange_app_selected() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_ALL; appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
@@ -397,7 +399,7 @@ public class BubblePreferenceControllerTest {
} }
@Test @Test
public void testOnPreferenceChange_app_none() { public void onPreferenceChange_app_none() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_ALL; appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
@@ -413,4 +415,17 @@ public class BubblePreferenceControllerTest {
assertEquals(BUBBLE_PREFERENCE_NONE, appRow.bubblePreference); assertEquals(BUBBLE_PREFERENCE_NONE, appRow.bubblePreference);
verify(mBackend, times(1)).setAllowBubbles(any(), anyInt(), eq(BUBBLE_PREFERENCE_NONE)); verify(mBackend, times(1)).setAllowBubbles(any(), anyInt(), eq(BUBBLE_PREFERENCE_NONE));
} }
@Test
public void onPreferenceChange_dependentFieldListenerCalled() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
mAppPageController.onResume(appRow, null, null, null, null, null);
BubblePreference pref = new BubblePreference(mContext);
mAppPageController.onPreferenceChange(pref, BUBBLE_PREFERENCE_NONE);
verify(mListener, times(1)).onFieldValueChanged();
}
} }

View File

@@ -23,7 +23,6 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
@@ -455,37 +454,6 @@ public class SliceBuilderUtilsTest {
assertThat(actualIconResource).isEqualTo(settingsIcon); assertThat(actualIconResource).isEqualTo(settingsIcon);
} }
@Test
public void buildUnavailableSlice_customizeSubtitle_returnsSliceWithCustomizedSubtitle() {
final String subtitleOfUnavailableSlice = "subtitleOfUnavailableSlice";
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE, 0 /* icon */,
subtitleOfUnavailableSlice);
Settings.Global.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
final Slice slice = SliceBuilderUtils.buildSlice(mContext, data);
final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
assertThat(metadata.getSubtitle()).isEqualTo(subtitleOfUnavailableSlice);
}
@Test
public void buildUnavailableSlice_notCustomizeSubtitle_returnsSliceWithDefaultSubtitle() {
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
SliceData.SliceType.SWITCH);
Settings.Global.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
final Slice slice = SliceBuilderUtils.buildSlice(mContext, data);
final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
assertThat(metadata.getSubtitle()).isEqualTo(
mContext.getString(R.string.disabled_dependent_setting_summary));
}
private SliceData getDummyData() { private SliceData getDummyData() {
return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE, return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH, SCREEN_TITLE,
ICON, null /* unavailableSliceSubtitle */); ICON, null /* unavailableSliceSubtitle */);