Snap for 4963158 from 6fdf8c225d to qt-release

Change-Id: I79abaef7f6b4b49918bb9ae74d07369c57b29abe
This commit is contained in:
android-build-team Robot
2018-08-19 03:10:43 +00:00
61 changed files with 1097 additions and 320 deletions

View File

@@ -3140,10 +3140,15 @@
</provider>
<receiver
android:name=".slices.SliceBroadcastReceiver" >
<intent-filter>
<action android:name="com.android.settings.slice.action.WIFI_CHANGED"/>
</intent-filter>
android:name=".slices.SliceBroadcastReceiver"
android:exported="false">
</receiver>
<receiver
android:name=".slices.SliceRelayReceiver"
android:permission="android.permission.MANAGE_SLICE_PERMISSIONS"
android:exported="true">
</receiver>
<!-- Couldn't be triggered from outside of settings. Statsd can trigger it because we send

View File

@@ -1,6 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="4">
<issue
id="LintError"
severity="Error"
message="No `.class` files were found in project &quot;.&quot;, so none of the classfile based checks could be run. Does the project need to be built first?"
category="Lint"
priority="10"
summary="Lint Failure"
explanation="This issue type represents a problem running lint itself. Examples include failure to find bytecode for source files (which means certain detectors could not be run), parsing errors in lint configuration files, etc.&#xA;These errors are not errors in your own code, but they are shown to make it clear that some checks were not completed.">
<location
file="."/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -1313,6 +1325,86 @@
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;face_anim_particle_color_1&quot;>#ff00bcd4&lt;/color> &lt;!-- Material Cyan 500 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="140"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;face_anim_particle_color_2&quot;>#ffef6c00&lt;/color> &lt;!-- Material Orange 800 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="141"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;face_anim_particle_color_3&quot;>#ff4caf50&lt;/color> &lt;!-- Material Green 500 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="142"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;face_anim_particle_color_4&quot;>#fffdd835&lt;/color> &lt;!-- Material Yellow 600 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="143"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;color name=&quot;face_anim_particle_error&quot;>#ff9e9e9e&lt;/color> &lt;!-- Material Gray 500 -->"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/colors.xml"
line="144"
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
@@ -2413,7 +2505,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="res/values/strings.xml"
line="5902"
line="5898"
column="36"/>
</issue>
@@ -2557,7 +2649,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="147"
line="151"
column="45"/>
</issue>
@@ -2573,7 +2665,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="148"
line="152"
column="49"/>
</issue>
@@ -2589,7 +2681,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="156"
line="160"
column="45"/>
</issue>
@@ -2605,7 +2697,7 @@
errorLine2=" ^">
<location
file="res/values/themes.xml"
line="157"
line="161"
column="49"/>
</issue>

View File

@@ -69,6 +69,8 @@
<declare-styleable name="Preference">
<!-- Synonyms for search results -->
<attr name="keywords" format="string" />
<!-- Whether or not the preference is searchable, by default it's true. -->
<attr name="searchable" format="boolean" />
<!-- Classname of a PreferenceController corresponding to the preference -->
<attr name="controller" format="string" />
<!-- {@code true} when the controller declared represents a slice from {@link android.app.SettingsSliceContract} -->

View File

@@ -3167,7 +3167,7 @@
<!-- In-progress title. This string lets the user know the SD card is being formatted. The user won't be able to proceed with setup until this step is finished. The placeholder is for the name of the device (e.g. brand name of the SD card). [CHAR LIMIT=32] -->
<string name="storage_wizard_format_progress_title">Formatting <xliff:g id="name" example="SD card">^1</xliff:g>\u2026</string>
<!-- Subtext for a full-screen title. This string lets the user know that the SD card can't be removed during this process. The user won't be able to proceed with setup until this step is finished. The placeholder is for the specific device (e.g. SD card, USB drive, etc.). [CHAR LIMIT=NONE] -->
<string name="storage_wizard_format_progress_body">Don\u2019t remove the <xliff:g id="name" example="SD card">^1</xliff:g> while it\u2019s being formatting.</string>
<string name="storage_wizard_format_progress_body">Don\u2019t remove the <xliff:g id="name" example="SD card">^1</xliff:g> while it\u2019s being formatted.</string>
<!-- Title of wizard step prompting user to migrate data to new storage [CHAR LIMIT=32] -->
<string name="storage_wizard_migrate_title">Move data to new storage</string>
@@ -9584,6 +9584,20 @@
<!-- Summary text for ambient display (device) [CHAR LIMIT=NONE]-->
<string name="ambient_display_pickup_summary" product="device">To check time, notifications, and other info, pick up your device.</string>
<!-- Preference and settings suggestion title text for reach gesture (phone) [CHAR LIMIT=60]-->
<string name="ambient_display_reach_title" product="default">Reach to check phone</string>
<!-- Preference and settings suggestion title text for reach gesture (tablet) [CHAR LIMIT=60]-->
<string name="ambient_display_reach_title" product="tablet">Reach to check tablet</string>
<!-- Preference and settings suggestion title text for reach gesture (device) [CHAR LIMIT=60]-->
<string name="ambient_display_reach_title" product="device">Reach to check device</string>
<!-- Summary text for ambient display (phone) [CHAR LIMIT=NONE]-->
<string name="ambient_display_reach_summary" product="default">To check time, notifications, and other info, reach for your phone.</string>
<!-- Summary text for ambient display (tablet) [CHAR LIMIT=NONE]-->
<string name="ambient_display_reach_summary" product="tablet">To check time, notifications, and other info, reach for your tablet.</string>
<!-- Summary text for ambient display (device) [CHAR LIMIT=NONE]-->
<string name="ambient_display_reach_summary" product="device">To check time, notifications, and other info, reach for your device.</string>
<!-- Title text for swiping downwards on fingerprint sensor for notifications [CHAR LIMIT=80]-->
<string name="fingerprint_swipe_for_notifications_title">Swipe fingerprint for notifications</string>
<!-- Title text for fingerprint gesture preference screen [CHAR LIMIT=25] -->

View File

@@ -71,6 +71,7 @@
android:key="special_access"
android:fragment="com.android.settings.applications.specialaccess.SpecialAccessSettings"
android:title="@string/special_access"
android:order="20" />
android:order="20"
settings:searchable="false"/>
</PreferenceScreen>

View File

@@ -25,7 +25,7 @@
android:key="assist_and_voice_input"
android:title="@string/assist_and_voice_input_title"
android:fragment="com.android.settings.applications.assist.ManageAssist"
settings:keywords="@string/keywords_assist_input"/>
settings:searchable="false"/>
<com.android.settings.widget.AppPreference
android:key="default_browser"
@@ -86,7 +86,8 @@
<com.android.settings.widget.AppPreference
android:key="work_default_browser"
android:title="@string/default_browser_title"
android:fragment="com.android.settings.applications.defaultapps.DefaultBrowserPicker">
android:fragment="com.android.settings.applications.defaultapps.DefaultBrowserPicker"
settings:searchable="false">
<extra android:name="for_work" android:value="true" />
</com.android.settings.widget.AppPreference>
@@ -94,7 +95,7 @@
android:key="work_default_phone_app"
android:title="@string/default_phone_title"
android:fragment="com.android.settings.applications.defaultapps.DefaultPhonePicker"
settings:keywords="@string/keywords_default_phone_app">
settings:searchable="false">
<extra android:name="for_work" android:value="true" />
</com.android.settings.widget.AppPreference>

View File

@@ -32,7 +32,7 @@
<com.android.settings.widget.WorkOnlyCategory
android:key="work_app_defaults"
android:key="autofill_work_app_defaults"
android:title="@string/default_for_work">
<com.android.settings.widget.GearPreference

View File

@@ -183,7 +183,8 @@
<Preference
android:key="feature_flags_dashboard"
android:title="@string/feature_flags_dashboard_title"
android:fragment="com.android.settings.development.featureflags.FeatureFlagsDashboard" />
android:fragment="com.android.settings.development.featureflags.FeatureFlagsDashboard"
settings:searchable="false" />
<SwitchPreference
android:key="enable_gpu_debug_layers"

View File

@@ -19,7 +19,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="manage_assist_screen"
android:title="@string/assist_and_voice_input_title">
android:title="@string/assist_and_voice_input_title"
settings:keywords="@string/keywords_assist_input">
<com.android.settings.widget.GearPreference
android:key="default_assist"

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:key="gesture_reach_screen"
android:title="@string/ambient_display_reach_title">
<com.android.settings.widget.VideoPreference
android:key="gesture_reach_video"
app:animation="@raw/gesture_ambient_lift"
app:preview="@drawable/gesture_ambient_lift" />
<SwitchPreference
android:key="gesture_reach"
android:title="@string/ambient_display_reach_title"
android:summary="@string/ambient_display_reach_summary"
app:keywords="@string/keywords_gesture"
app:controller="com.android.settings.gestures.ReachGesturePreferenceController"
app:allowDividerAbove="true" />
</PreferenceScreen>

View File

@@ -97,13 +97,5 @@ public class AppAndNotificationDashboardFragment extends DashboardFragment {
Context context) {
return buildPreferenceControllers(context, null, null /* host */);
}
@Override
public List<String> getNonIndexableKeys(Context context) {
List<String> keys = super.getNonIndexableKeys(context);
keys.add((new SpecialAppAccessPreferenceController(context))
.getPreferenceKey());
return keys;
}
};
}

View File

@@ -101,16 +101,6 @@ public class DefaultAppSettings extends DashboardFragment {
return Arrays.asList(sir);
}
@Override
public List<String> getNonIndexableKeys(Context context) {
List<String> keys = super.getNonIndexableKeys(context);
keys.add(KEY_ASSIST_VOICE_INPUT);
// TODO (b/38230148) Remove these keys when we can differentiate work results
keys.add(DefaultWorkPhonePreferenceController.KEY);
keys.add(DefaultWorkBrowserPreferenceController.KEY);
return keys;
}
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {

View File

@@ -35,6 +35,7 @@ import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceClickListener;
import com.android.internal.content.PackageMonitor;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
@@ -168,11 +169,15 @@ public class DefaultAutofillPicker extends DefaultAppPickerFragment {
}
final Intent addNewServiceIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(searchUri));
Preference preference = new Preference(getPrefContext());
final Context context = getPrefContext();
final Preference preference = new Preference(context);
preference.setOnPreferenceClickListener(p -> {
context.startActivityAsUser(addNewServiceIntent, UserHandle.of(mUserId));
return true;
});
preference.setTitle(R.string.print_menu_item_add_service);
preference.setIcon(R.drawable.ic_menu_add);
preference.setOrder(Integer.MAX_VALUE -1);
preference.setIntent(addNewServiceIntent);
preference.setPersistent(false);
return preference;
}

View File

@@ -40,7 +40,7 @@ public class BackupSettingsActivityPreferenceController extends BasePreferenceCo
@Override
public int getAvailabilityStatus() {
return mUm.isAdminUser()
? AVAILABLE
? AVAILABLE_UNSEARCHABLE
: UNSUPPORTED_ON_DEVICE;
}

View File

@@ -23,9 +23,7 @@ import android.util.Log;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
/**
@@ -45,15 +43,6 @@ public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
@VisibleForTesting
AvailableMediaBluetoothDeviceUpdater(DashboardFragment fragment,
DevicePreferenceCallback devicePreferenceCallback,
LocalBluetoothManager localBluetoothManager) {
super(fragment, devicePreferenceCallback, localBluetoothManager);
mAudioManager = (AudioManager) fragment.getContext().
getSystemService(Context.AUDIO_SERVICE);
}
@Override
public void onAudioModeChanged() {
forceUpdate();

View File

@@ -149,15 +149,12 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll
*/
private void disableProfile(LocalBluetoothProfile profile, BluetoothDevice device,
SwitchPreference profilePref) {
if (profile instanceof PbapServerProfile) {
mCachedDevice.setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_REJECTED);
// We don't need to do the additional steps below for this profile.
return;
}
mCachedDevice.disconnect(profile);
profile.setPreferred(device, false);
if (profile instanceof MapProfile) {
mCachedDevice.setMessagePermissionChoice(BluetoothDevice.ACCESS_REJECTED);
} else if (profile instanceof PbapServerProfile) {
mCachedDevice.setPhonebookPermissionChoice(CachedBluetoothDevice.ACCESS_REJECTED);
}
}

View File

@@ -207,8 +207,7 @@ public class BluetoothPermissionActivity extends AlertActivity implements
bluetoothManager.getCachedDeviceManager();
CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice);
if (cachedDevice == null) {
cachedDevice = cachedDeviceManager.addDevice(bluetoothManager.getBluetoothAdapter(),
mDevice);
cachedDevice = cachedDeviceManager.addDevice(mDevice);
}
always = cachedDevice.checkAndIncreaseMessageRejectionCount();
}

View File

@@ -231,8 +231,7 @@ public final class BluetoothPermissionRequest extends BroadcastReceiver {
bluetoothManager.getCachedDeviceManager();
CachedBluetoothDevice cachedDevice = cachedDeviceManager.findDevice(mDevice);
if (cachedDevice == null) {
cachedDevice = cachedDeviceManager.addDevice(bluetoothManager.getBluetoothAdapter(),
mDevice);
cachedDevice = cachedDeviceManager.addDevice(mDevice);
}
String intentName = BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY;

View File

@@ -24,9 +24,7 @@ import android.util.Log;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
/**
@@ -45,15 +43,6 @@ public class ConnectedBluetoothDeviceUpdater extends BluetoothDeviceUpdater {
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
@VisibleForTesting
ConnectedBluetoothDeviceUpdater(DashboardFragment fragment,
DevicePreferenceCallback devicePreferenceCallback,
LocalBluetoothManager localBluetoothManager) {
super(fragment, devicePreferenceCallback, localBluetoothManager);
mAudioManager = (AudioManager) fragment.getContext().
getSystemService(Context.AUDIO_SERVICE);
}
@Override
public void onAudioModeChanged() {
forceUpdate();

View File

@@ -16,16 +16,13 @@
package com.android.settings.bluetooth;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
/**
@@ -41,13 +38,6 @@ public class SavedBluetoothDeviceUpdater extends BluetoothDeviceUpdater
super(context, fragment, devicePreferenceCallback);
}
@VisibleForTesting
SavedBluetoothDeviceUpdater(DashboardFragment fragment,
DevicePreferenceCallback devicePreferenceCallback,
LocalBluetoothManager localBluetoothManager) {
super(fragment, devicePreferenceCallback, localBluetoothManager);
}
@Override
public boolean isFilterMatched(CachedBluetoothDevice cachedDevice) {
final BluetoothDevice device = cachedDevice.getDevice();

View File

@@ -274,6 +274,10 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
Log.w(TAG, "Skipping updateNonIndexableKeys due to empty key " + toString());
return;
}
if (keys.contains(key)) {
Log.w(TAG, "Skipping updateNonIndexableKeys, key already in list. " + toString());
return;
}
keys.add(key);
}
}

View File

@@ -42,7 +42,12 @@ public interface PreferenceControllerMixin {
final String key = ((AbstractPreferenceController) this).getPreferenceKey();
if (TextUtils.isEmpty(key)) {
Log.w(TAG,
"Skipping updateNonIndexableKeys due to empty key " + this.toString());
"Skipping updateNonIndexableKeys due to empty key " + toString());
return;
}
if (keys.contains(key)) {
Log.w(TAG, "Skipping updateNonIndexableKeys, key already in list. "
+ toString());
return;
}
keys.add(key);

View File

@@ -29,6 +29,9 @@ import android.util.Log;
import android.util.TypedValue;
import android.util.Xml;
import androidx.annotation.IntDef;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import org.xmlpull.v1.XmlPullParser;
@@ -41,9 +44,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import androidx.annotation.IntDef;
import androidx.annotation.VisibleForTesting;
/**
* Utility class to parse elements of XML preferences
*/
@@ -53,7 +53,8 @@ public class PreferenceXmlParserUtils {
@VisibleForTesting
static final String PREF_SCREEN_TAG = "PreferenceScreen";
private static final List<String> SUPPORTED_PREF_TYPES = Arrays.asList(
"Preference", "PreferenceCategory", "PreferenceScreen");
"Preference", "PreferenceCategory", "PreferenceScreen",
"com.android.settings.widget.WorkOnlyCategory");
/**
* Flag definition to indicate which metadata should be extracted when
@@ -67,7 +68,8 @@ public class PreferenceXmlParserUtils {
MetadataFlag.FLAG_NEED_PREF_CONTROLLER,
MetadataFlag.FLAG_NEED_PREF_TITLE,
MetadataFlag.FLAG_NEED_PREF_SUMMARY,
MetadataFlag.FLAG_NEED_PREF_ICON})
MetadataFlag.FLAG_NEED_PREF_ICON,
MetadataFlag.FLAG_NEED_SEARCHABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface MetadataFlag {
int FLAG_INCLUDE_PREF_SCREEN = 1;
@@ -79,6 +81,7 @@ public class PreferenceXmlParserUtils {
int FLAG_NEED_PREF_ICON = 1 << 6;
int FLAG_NEED_PLATFORM_SLICE_FLAG = 1 << 7;
int FLAG_NEED_KEYWORDS = 1 << 8;
int FLAG_NEED_SEARCHABLE = 1 << 9;
}
public static final String METADATA_PREF_TYPE = "type";
@@ -89,6 +92,7 @@ public class PreferenceXmlParserUtils {
public static final String METADATA_ICON = "icon";
public static final String METADATA_PLATFORM_SLICE_FLAG = "platform_slice";
public static final String METADATA_KEYWORDS = "keywords";
public static final String METADATA_SEARCHABLE = "searchable";
private static final String ENTRIES_SEPARATOR = "|";
@@ -154,18 +158,6 @@ public class PreferenceXmlParserUtils {
R.styleable.Preference_controller);
}
/**
* Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_ICON} instead.
*/
@Deprecated
public static int getDataIcon(Context context, AttributeSet attrs) {
final TypedArray ta = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.Preference);
final int dataIcon = ta.getResourceId(com.android.internal.R.styleable.Icon_icon, 0);
ta.recycle();
return dataIcon;
}
/**
* Extracts metadata from preference xml and put them into a {@link Bundle}.
*
@@ -232,6 +224,10 @@ public class PreferenceXmlParserUtils {
if (hasFlag(flags, MetadataFlag.FLAG_NEED_KEYWORDS)) {
preferenceMetadata.putString(METADATA_KEYWORDS, getKeywords(preferenceAttributes));
}
if (hasFlag(flags, MetadataFlag.FLAG_NEED_SEARCHABLE)) {
preferenceMetadata.putBoolean(METADATA_SEARCHABLE,
isSearchable(preferenceAttributes));
}
metadata.add(preferenceMetadata);
preferenceAttributes.recycle();
@@ -312,6 +308,10 @@ public class PreferenceXmlParserUtils {
return styledAttributes.getBoolean(R.styleable.Preference_platform_slice, false /* def */);
}
private static boolean isSearchable(TypedArray styledAttributes) {
return styledAttributes.getBoolean(R.styleable.Preference_searchable, true /* default */);
}
private static String getKeywords(TypedArray styleAttributes) {
return styleAttributes.getString(R.styleable.Preference_keywords);
}

View File

@@ -21,6 +21,7 @@ import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
@@ -30,7 +31,7 @@ final class AutofillDeveloperSettingsObserver extends ContentObserver {
private final ContentResolver mResolver;
public AutofillDeveloperSettingsObserver(Context context, Runnable changeCallback) {
super(new Handler());
super(new Handler(Looper.getMainLooper()));
mResolver = context.getContentResolver();
mChangeCallback = changeCallback;

View File

@@ -31,8 +31,8 @@ import androidx.annotation.VisibleForTesting;
public class PickupGesturePreferenceController extends GesturePreferenceController {
private final int ON = 1;
private final int OFF = 0;
private static final int ON = 1;
private static final int OFF = 0;
private static final String PREF_KEY_VIDEO = "gesture_pick_up_video";
private final String mPickUpPrefKey;

View File

@@ -0,0 +1,96 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.gestures;
import static android.provider.Settings.Secure.DOZE_REACH_GESTURE;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import com.android.internal.hardware.AmbientDisplayConfiguration;
public class ReachGesturePreferenceController extends GesturePreferenceController {
private static final int ON = 1;
private static final int OFF = 0;
private static final String PREF_KEY_VIDEO = "gesture_reach_video";
private final String mReachUpPrefKey;
private AmbientDisplayConfiguration mAmbientConfig;
@UserIdInt
private final int mUserId;
public ReachGesturePreferenceController(Context context, String key) {
super(context, key);
mUserId = UserHandle.myUserId();
mReachUpPrefKey = key;
}
public ReachGesturePreferenceController setConfig(AmbientDisplayConfiguration config) {
mAmbientConfig = config;
return this;
}
@Override
public int getAvailabilityStatus() {
// No hardware support for Reach Gesture
if (!getAmbientConfig().reachGestureAvailable()) {
return UNSUPPORTED_ON_DEVICE;
}
return AVAILABLE;
}
@Override
public boolean isSliceable() {
return TextUtils.equals(getPreferenceKey(), "gesture_reach");
}
@Override
protected String getVideoPrefKey() {
return PREF_KEY_VIDEO;
}
@Override
public boolean isChecked() {
return getAmbientConfig().reachGestureEnabled(mUserId);
}
@Override
public String getPreferenceKey() {
return mReachUpPrefKey;
}
@Override
public boolean setChecked(boolean isChecked) {
return Settings.Secure.putInt(mContext.getContentResolver(), DOZE_REACH_GESTURE,
isChecked ? ON : OFF);
}
private AmbientDisplayConfiguration getAmbientConfig() {
if (mAmbientConfig == null) {
mAmbientConfig = new AmbientDisplayConfiguration(mContext);
}
return mAmbientConfig;
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.gestures;
import android.content.Context;
import android.content.SharedPreferences;
import android.provider.SearchIndexableResource;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
import java.util.Arrays;
import java.util.List;
@SearchIndexable
public class ReachGestureSettings extends DashboardFragment {
private static final String TAG = "ReachGestureSettings";
public static final String PREF_KEY_SUGGESTION_COMPLETE =
"pref_reach_gesture_suggestion_complete";
@Override
public void onAttach(Context context) {
super.onAttach(context);
SuggestionFeatureProvider suggestionFeatureProvider = FeatureFactory.getFactory(context)
.getSuggestionFeatureProvider(context);
SharedPreferences prefs = suggestionFeatureProvider.getSharedPrefs(context);
prefs.edit().putBoolean(PREF_KEY_SUGGESTION_COMPLETE, true).apply();
use(ReachGesturePreferenceController.class)
.setConfig(new AmbientDisplayConfiguration(context));
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.SETTINGS_GESTURE_REACH;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.reach_gesture_settings;
}
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.reach_gesture_settings;
return Arrays.asList(sir);
}
};
}

View File

@@ -47,6 +47,9 @@ public class SwipeUpPreferenceController extends GesturePreferenceController {
final ComponentName recentsComponentName = ComponentName.unflattenFromString(
context.getString(R.string.config_recentsComponentName));
if (recentsComponentName == null) {
return false;
}
final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
.setPackage(recentsComponentName.getPackageName());
if (context.getPackageManager().resolveService(quickStepIntent,

View File

@@ -29,6 +29,8 @@ import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.android.settingslib.utils.ThreadUtils;
/**
* Provider stores and manages user interaction feedback for homepage contextual cards.
*/
@@ -61,9 +63,7 @@ public class CardContentProvider extends ContentProvider {
public Uri insert(Uri uri, ContentValues values) {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
try {
if (Build.IS_DEBUGGABLE) {
enableStrictMode(true);
}
maybeEnableStrictMode();
final SQLiteDatabase database = mDBHelper.getWritableDatabase();
final String table = getTableFromMatch(uri);
@@ -84,10 +84,7 @@ public class CardContentProvider extends ContentProvider {
public int delete(Uri uri, String selection, String[] selectionArgs) {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
try {
if (Build.IS_DEBUGGABLE) {
enableStrictMode(true);
}
maybeEnableStrictMode();
final SQLiteDatabase database = mDBHelper.getWritableDatabase();
final String table = getTableFromMatch(uri);
final int rowsDeleted = database.delete(table, selection, selectionArgs);
@@ -108,9 +105,7 @@ public class CardContentProvider extends ContentProvider {
String[] selectionArgs, String sortOrder) {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
try {
if (Build.IS_DEBUGGABLE) {
enableStrictMode(true);
}
maybeEnableStrictMode();
final SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
final String table = getTableFromMatch(uri);
@@ -130,9 +125,7 @@ public class CardContentProvider extends ContentProvider {
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
try {
if (Build.IS_DEBUGGABLE) {
enableStrictMode(true);
}
maybeEnableStrictMode();
final SQLiteDatabase database = mDBHelper.getWritableDatabase();
final String table = getTableFromMatch(uri);
@@ -144,10 +137,16 @@ public class CardContentProvider extends ContentProvider {
}
}
private void enableStrictMode(boolean enabled) {
StrictMode.setThreadPolicy(enabled
? new StrictMode.ThreadPolicy.Builder().detectAll().build()
: StrictMode.ThreadPolicy.LAX);
@VisibleForTesting
void maybeEnableStrictMode() {
if (Build.IS_DEBUGGABLE && ThreadUtils.isMainThread()) {
enableStrictMode();
}
}
@VisibleForTesting
void enableStrictMode() {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().build());
}
@VisibleForTesting

View File

@@ -28,6 +28,13 @@ import com.android.settings.homepage.conditional.ConditionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class ConditionManager {
private static final String TAG = "ConditionManager";
@@ -37,6 +44,9 @@ public class ConditionManager {
@VisibleForTesting
final List<ConditionalCardController> mCardControllers;
private static final long DISPLAYABLE_CHECKER_TIMEOUT_MS = 20;
private final ExecutorService mExecutorService;
private final Context mAppContext;
private final ConditionListener mListener;
@@ -51,6 +61,7 @@ public class ConditionManager {
public ConditionManager(Context context, ConditionListener listener) {
mAppContext = context.getApplicationContext();
mExecutorService = Executors.newCachedThreadPool();
mCandidates = new ArrayList<>();
mCardControllers = new ArrayList<>();
mListener = listener;
@@ -62,9 +73,23 @@ public class ConditionManager {
*/
public List<ConditionalCard> getDisplayableCards() {
final List<ConditionalCard> cards = new ArrayList<>();
final List<Future<ConditionalCard>> displayableCards = new ArrayList<>();
// Check displayable future
for (ConditionalCard card : mCandidates) {
if (getController(card.getId()).isDisplayable()) {
cards.add(card);
final DisplayableChecker future = new DisplayableChecker(
card, getController(card.getId()));
displayableCards.add(mExecutorService.submit(future));
}
// Collect future and add displayable cards
for (Future<ConditionalCard> cardFuture : displayableCards) {
try {
final ConditionalCard card = cardFuture.get(DISPLAYABLE_CHECKER_TIMEOUT_MS,
TimeUnit.MILLISECONDS);
if (card != null) {
cards.add(card);
}
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Log.w(TAG, "Failed to get displayable state for card, likely timeout. Skipping", e);
}
}
return cards;
@@ -89,7 +114,6 @@ public class ConditionManager {
onConditionChanged();
}
/**
* Start monitoring state change for all conditions
*/
@@ -163,6 +187,24 @@ public class ConditionManager {
mCandidates.add(new RingerMutedConditionCard(mAppContext));
mCandidates.add(new RingerVibrateConditionCard(mAppContext));
mCandidates.add(new WorkModeConditionCard(mAppContext));
}
/**
* Returns card if controller says it's displayable. Otherwise returns null.
*/
public static class DisplayableChecker implements Callable<ConditionalCard> {
private final ConditionalCard mCard;
private final ConditionalCardController mController;
private DisplayableChecker(ConditionalCard card, ConditionalCardController controller) {
mCard = card;
mController = controller;
}
@Override
public ConditionalCard call() throws Exception {
return mController.isDisplayable() ? mCard : null;
}
}
}

View File

@@ -108,7 +108,7 @@ public class LanguageAndInputSettings extends DashboardFragment {
// Pointer and Tts
final TtsPreferenceController ttsPreferenceController =
new TtsPreferenceController(context, new TtsEngines(context));
new TtsPreferenceController(context, KEY_TEXT_TO_SPEECH);
controllers.add(ttsPreferenceController);
final PointerSpeedController pointerController = new PointerSpeedController(context);
controllers.add(pointerController);
@@ -180,7 +180,6 @@ public class LanguageAndInputSettings extends DashboardFragment {
public List<String> getNonIndexableKeys(Context context) {
List<String> keys = super.getNonIndexableKeys(context);
// Duplicates in summary and details pages.
keys.add(KEY_TEXT_TO_SPEECH);
keys.add(KEY_PHYSICAL_KEYBOARD);
return keys;
}

View File

@@ -19,31 +19,26 @@ package com.android.settings.language;
import android.content.Context;
import android.speech.tts.TtsEngines;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settings.core.BasePreferenceController;
public class TtsPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin {
public class TtsPreferenceController extends BasePreferenceController {
private static final String KEY_VOICE_CATEGORY = "voice_category";
private static final String KEY_TTS_SETTINGS = "tts_settings_summary";
@VisibleForTesting
TtsEngines mTtsEngines;
private final TtsEngines mTtsEngines;
public TtsPreferenceController(Context context, TtsEngines ttsEngines) {
super(context);
mTtsEngines = ttsEngines;
public TtsPreferenceController(Context context, String key) {
super(context, key);
mTtsEngines = new TtsEngines(context);
}
@Override
public boolean isAvailable() {
public int getAvailabilityStatus() {
return !mTtsEngines.getEngines().isEmpty() &&
mContext.getResources().getBoolean(R.bool.config_show_tts_settings_summary);
}
@Override
public String getPreferenceKey() {
return KEY_TTS_SETTINGS;
mContext.getResources().getBoolean(R.bool.config_show_tts_settings_summary)
? AVAILABLE_UNSEARCHABLE
: CONDITIONALLY_UNAVAILABLE;
}
}

View File

@@ -16,14 +16,21 @@
package com.android.settings.search;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SEARCHABLE;
import static com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag
.FLAG_INCLUDE_PREF_SCREEN;
import static com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag.FLAG_NEED_KEY;
import static com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag.FLAG_NEED_SEARCHABLE;
import android.annotation.XmlRes;
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
import androidx.annotation.CallSuper;
import androidx.annotation.VisibleForTesting;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerListHelper;
@@ -31,16 +38,12 @@ import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.PreferenceXmlParserUtils;
import com.android.settingslib.core.AbstractPreferenceController;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.CallSuper;
import androidx.annotation.VisibleForTesting;
/**
* A basic SearchIndexProvider that returns no data to index.
*/
@@ -66,11 +69,12 @@ public class BaseSearchIndexProvider implements Indexable.SearchIndexProvider {
public List<String> getNonIndexableKeys(Context context) {
if (!isPageSearchEnabled(context)) {
// Entire page should be suppressed, mark all keys from this page as non-indexable.
return getNonIndexableKeysFromXml(context);
return getNonIndexableKeysFromXml(context, true /* suppressAllPage */);
}
final List<String> nonIndexableKeys = new ArrayList<>();
nonIndexableKeys.addAll(getNonIndexableKeysFromXml(context, false /* suppressAllPage */));
final List<AbstractPreferenceController> controllers = getPreferenceControllers(context);
if (controllers != null && !controllers.isEmpty()) {
final List<String> nonIndexableKeys = new ArrayList<>();
for (AbstractPreferenceController controller : controllers) {
if (controller instanceof PreferenceControllerMixin) {
((PreferenceControllerMixin) controller)
@@ -85,10 +89,8 @@ public class BaseSearchIndexProvider implements Indexable.SearchIndexProvider {
nonIndexableKeys.add(controller.getPreferenceKey());
}
}
return nonIndexableKeys;
} else {
return new ArrayList<>();
}
return nonIndexableKeys;
}
@Override
@@ -131,7 +133,11 @@ public class BaseSearchIndexProvider implements Indexable.SearchIndexProvider {
return true;
}
private List<String> getNonIndexableKeysFromXml(Context context) {
/**
* Get all non-indexable keys from xml. If {@param suppressAllPage} is set, all keys are
* considered non-indexable. Otherwise, only keys with searchable="false" are included.
*/
private List<String> getNonIndexableKeysFromXml(Context context, boolean suppressAllPage) {
final List<SearchIndexableResource> resources = getXmlResourcesToIndex(
context, true /* not used*/);
if (resources == null || resources.isEmpty()) {
@@ -139,27 +145,32 @@ public class BaseSearchIndexProvider implements Indexable.SearchIndexProvider {
}
final List<String> nonIndexableKeys = new ArrayList<>();
for (SearchIndexableResource res : resources) {
nonIndexableKeys.addAll(getNonIndexableKeysFromXml(context, res.xmlResId));
nonIndexableKeys.addAll(
getNonIndexableKeysFromXml(context, res.xmlResId, suppressAllPage));
}
return nonIndexableKeys;
}
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
public List<String> getNonIndexableKeysFromXml(Context context, @XmlRes int xmlResId) {
final List<String> nonIndexableKeys = new ArrayList<>();
final XmlResourceParser parser = context.getResources().getXml(xmlResId);
final AttributeSet attrs = Xml.asAttributeSet(parser);
public List<String> getNonIndexableKeysFromXml(Context context, @XmlRes int xmlResId,
boolean suppressAllPage) {
return getKeysFromXml(context, xmlResId, suppressAllPage);
}
private List<String> getKeysFromXml(Context context, @XmlRes int xmlResId,
boolean suppressAllPage) {
final List<String> keys = new ArrayList<>();
try {
while (parser.next() != XmlPullParser.END_DOCUMENT) {
final String key = PreferenceXmlParserUtils.getDataKey(context, attrs);
if (!TextUtils.isEmpty(key)) {
nonIndexableKeys.add(key);
final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(context,
xmlResId, FLAG_NEED_KEY | FLAG_INCLUDE_PREF_SCREEN | FLAG_NEED_SEARCHABLE);
for (Bundle bundle : metadata) {
if (suppressAllPage || !bundle.getBoolean(METADATA_SEARCHABLE, true)) {
keys.add(bundle.getString(METADATA_KEY));
}
}
} catch (IOException | XmlPullParserException e) {
Log.w(TAG, "Error parsing non-indexable from xml " + xmlResId);
}
return nonIndexableKeys;
return keys;
}
}

View File

@@ -43,6 +43,7 @@ import androidx.slice.SliceViewManager;
import androidx.slice.SliceViewManager.SliceCallback;
import androidx.slice.core.SliceQuery;
import androidx.slice.widget.ListContent;
import androidx.slice.widget.SliceContent;
public class DeviceIndexUpdateJobService extends JobService {
@@ -134,7 +135,7 @@ public class DeviceIndexUpdateJobService extends JobService {
protected CharSequence findTitle(Slice loadedSlice, SliceMetadata metaData) {
ListContent content = new ListContent(null, loadedSlice);
SliceItem headerItem = content.getHeaderItem();
SliceContent headerItem = content.getHeader();
if (headerItem == null) {
if (content.getRowItems().size() != 0) {
headerItem = content.getRowItems().get(0);
@@ -143,15 +144,15 @@ public class DeviceIndexUpdateJobService extends JobService {
}
}
// Look for a title, then large text, then any text at all.
SliceItem title = SliceQuery.find(headerItem, FORMAT_TEXT, HINT_TITLE, null);
SliceItem title = SliceQuery.find(headerItem.getSliceItem(), FORMAT_TEXT, HINT_TITLE, null);
if (title != null) {
return title.getText();
}
title = SliceQuery.find(headerItem, FORMAT_TEXT, HINT_LARGE, null);
title = SliceQuery.find(headerItem.getSliceItem(), FORMAT_TEXT, HINT_LARGE, null);
if (title != null) {
return title.getText();
}
title = SliceQuery.find(headerItem, FORMAT_TEXT);
title = SliceQuery.find(headerItem.getSliceItem(), FORMAT_TEXT);
if (title != null) {
return title.getText();
}

View File

@@ -423,7 +423,7 @@ public class SettingsSliceProvider extends SliceProvider {
void registerIntentToUri(IntentFilter intentFilter, Uri sliceUri) {
Log.d(TAG, "Registering Uri for broadcast relay: " + sliceUri);
mRegisteredUris.add(sliceUri);
SliceBroadcastRelay.registerReceiver(getContext(), sliceUri, SliceBroadcastReceiver.class,
SliceBroadcastRelay.registerReceiver(getContext(), sliceUri, SliceRelayReceiver.class,
intentFilter);
}

View File

@@ -55,7 +55,6 @@ import com.android.settings.flashlight.FlashlightSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.wifi.WifiSliceBuilder;
import com.android.settingslib.SliceBroadcastRelay;
/**
* Responds to actions performed on slices and notifies slices of updates in state changes.
@@ -121,12 +120,6 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
case ACTION_FLASHLIGHT_SLICE_CHANGED:
FlashlightSliceBuilder.handleUriChange(context, intent);
break;
default:
final String uriString = intent.getStringExtra(SliceBroadcastRelay.EXTRA_URI);
if (!TextUtils.isEmpty(uriString)) {
final Uri uri = Uri.parse(uriString);
context.getContentResolver().notifyChange(uri, null /* observer */);
}
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.settings.slices;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import com.android.settingslib.SliceBroadcastRelay;
/**
* Receives broadcasts to notify that Settings Slices are potentially stale.
*/
public class SliceRelayReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
final String uriString = intent.getStringExtra(SliceBroadcastRelay.EXTRA_URI);
if (!TextUtils.isEmpty(uriString)) {
final Uri uri = Uri.parse(uriString);
context.getContentResolver().notifyChange(uri, null /* observer */);
}
}
}

View File

@@ -101,8 +101,6 @@ public class SystemDashboardFragment extends DashboardFragment {
@Override
public List<String> getNonIndexableKeys(Context context) {
List<String> keys = super.getNonIndexableKeys(context);
keys.add((new BackupSettingsActivityPreferenceController(
context).getPreferenceKey()));
keys.add(KEY_RESET);
return keys;
}

View File

@@ -49,6 +49,13 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.SimpleAdapter;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.UserIcons;
import com.android.internal.widget.LockPatternUtils;
@@ -76,13 +83,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
/**
* Screen that manages the list of users on the device.
* Guest user is an always visible entry, even if the guest is not currently
@@ -635,8 +635,8 @@ public class UserSettings extends SettingsPreferenceFragment
AlertDialog.Builder builder = new AlertDialog.Builder(context);
SimpleAdapter adapter = new SimpleAdapter(builder.getContext(),
data, R.layout.two_line_list_item,
new String[] {KEY_TITLE, KEY_SUMMARY},
new int[] {R.id.title, R.id.summary});
new String[]{KEY_TITLE, KEY_SUMMARY},
new int[]{R.id.title, R.id.summary});
builder.setTitle(R.string.user_add_user_type_title);
builder.setAdapter(adapter,
new DialogInterface.OnClickListener() {
@@ -1238,8 +1238,10 @@ public class UserSettings extends SettingsPreferenceFragment
}
@Override
public List<String> getNonIndexableKeysFromXml(Context context, int xmlResId) {
final List<String> niks = super.getNonIndexableKeysFromXml(context, xmlResId);
public List<String> getNonIndexableKeysFromXml(Context context, int xmlResId,
boolean suppressAllPage) {
final List<String> niks = super.getNonIndexableKeysFromXml(context, xmlResId,
suppressAllPage);
new AddUserWhenLockedPreferenceController(context, KEY_ADD_USER_WHEN_LOCKED)
.updateNonIndexableKeys(niks);
new AutoSyncDataPreferenceController(context, null /* parent */)

View File

@@ -24,6 +24,7 @@ import android.app.Activity;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.net.ConnectivityManager;
@@ -87,7 +88,7 @@ import java.util.List;
@SearchIndexable
public class WifiSettings extends RestrictedSettingsFragment
implements Indexable, WifiTracker.WifiListener, AccessPointListener,
WifiDialog.WifiDialogListener {
WifiDialog.WifiDialogListener, DialogInterface.OnDismissListener {
private static final String TAG = "WifiSettings";
@@ -432,9 +433,8 @@ public class WifiSettings extends RestrictedSettingsFragment
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// If the dialog is showing, save its state.
if (mDialog != null && mDialog.isShowing()) {
// If dialog has been shown, save its state.
if (mDialog != null) {
outState.putInt(SAVE_DIALOG_MODE, mDialogMode);
if (mDlgAccessPoint != null) {
mAccessPointSavedState = new Bundle();
@@ -443,7 +443,7 @@ public class WifiSettings extends RestrictedSettingsFragment
}
}
if (mWifiToNfcDialog != null && mWifiToNfcDialog.isShowing()) {
if (mWifiToNfcDialog != null) {
Bundle savedState = new Bundle();
mWifiToNfcDialog.saveState(savedState);
outState.putBundle(SAVED_WIFI_NFC_DIALOG_STATE, savedState);
@@ -617,12 +617,24 @@ public class WifiSettings extends RestrictedSettingsFragment
mWifiToNfcDialog = new WriteWifiConfigToNfcDialog(getActivity(),
mWifiNfcDialogSavedState);
}
return mWifiToNfcDialog;
}
return super.onCreateDialog(dialogId);
}
@Override
public void onDialogShowing() {
super.onDialogShowing();
setOnDismissListener(this);
}
@Override
public void onDismiss(DialogInterface dialog) {
// We don't keep any dialog object when dialog was dismissed.
mDialog = null;
mWifiToNfcDialog = null;
}
@Override
public int getDialogMetricsCategory(int dialogId) {
switch (dialogId) {

View File

@@ -355,11 +355,9 @@ public class WifiP2pSettings extends DashboardFragment
int textId = mWifiP2pSearching ? R.string.wifi_p2p_menu_searching :
R.string.wifi_p2p_menu_search;
menu.add(Menu.NONE, MENU_ID_SEARCH, 0, textId)
.setEnabled(mWifiP2pEnabled)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
.setEnabled(mWifiP2pEnabled);
menu.add(Menu.NONE, MENU_ID_RENAME, 0, R.string.wifi_p2p_menu_rename)
.setEnabled(mWifiP2pEnabled)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
.setEnabled(mWifiP2pEnabled);
super.onCreateOptionsMenu(menu, inflater);
}

View File

@@ -59,5 +59,6 @@
android:title="pref_title_5"
android:summaryOn="summary_on"
android:summaryOff="summary_off"
settings:searchable="false"
settings:keywords="keywords1, keywords2, keywords3" />
</PreferenceScreen>

View File

@@ -17,6 +17,7 @@
package com.android.settings.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -26,7 +27,6 @@ import android.os.UserManager;
import com.android.settings.notification.EmergencyBroadcastPreferenceController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.XmlTestUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -42,19 +42,16 @@ public class AppAndNotificationDashboardFragmentTest {
@Test
@Config(shadows = {ShadowEmergencyBroadcastPreferenceController.class})
public void testNonIndexableKeys_existInXmlLayout() {
public void getNonIndexableKeys_shouldIncludeSpecialAppAccess() {
final Context context = spy(RuntimeEnvironment.application);
UserManager manager = mock(UserManager.class);
when(manager.isAdminUser()).thenReturn(true);
when(context.getSystemService(Context.USER_SERVICE)).thenReturn(manager);
final List<String> niks = AppAndNotificationDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(context);
AppAndNotificationDashboardFragment fragment = new AppAndNotificationDashboardFragment();
final int xmlId = fragment.getPreferenceScreenResId();
final List<String> keys = XmlTestUtils.getKeysFromPreferenceXml(context, xmlId);
assertThat(keys).containsAllIn(niks);
assertThat(niks).contains(
new SpecialAppAccessPreferenceController(context).getPreferenceKey());
}
@Implements(EmergencyBroadcastPreferenceController.class)

View File

@@ -165,7 +165,7 @@ public class DefaultAppSettingsTest {
final List<String> niks = DefaultAppSettings.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(context);
final int xmlId = (new DefaultAppSettings()).getPreferenceScreenResId();
final int xmlId = new DefaultAppSettings().getPreferenceScreenResId();
final List<String> keys = XmlTestUtils.getKeysFromPreferenceXml(context, xmlId);

View File

@@ -33,10 +33,9 @@ import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowAudioManager;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowCachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.HeadsetProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import org.junit.Before;
@@ -52,7 +51,8 @@ import java.util.ArrayList;
import java.util.Collection;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {ShadowAudioManager.class, ShadowBluetoothAdapter.class})
@Config(shadows = {ShadowAudioManager.class, ShadowBluetoothAdapter.class,
ShadowCachedBluetoothDeviceManager.class})
public class AvailableMediaBluetoothDeviceUpdaterTest {
@Mock
private DashboardFragment mDashboardFragment;
@@ -62,21 +62,14 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
private CachedBluetoothDevice mCachedBluetoothDevice;
@Mock
private BluetoothDevice mBluetoothDevice;
@Mock
private LocalBluetoothManager mLocalManager;
@Mock
private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
@Mock
private HeadsetProfile mHeadsetProfile;
@Mock
private CachedBluetoothDeviceManager mCachedDeviceManager;
private Context mContext;
private AvailableMediaBluetoothDeviceUpdater mBluetoothDeviceUpdater;
private Collection<CachedBluetoothDevice> cachedDevices;
private Collection<CachedBluetoothDevice> mCachedDevices;
private ShadowAudioManager mShadowAudioManager;
private BluetoothDevicePreference mPreference;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
private ShadowCachedBluetoothDeviceManager mShadowCachedBluetoothDeviceManager;
@Before
public void setUp() {
@@ -86,18 +79,17 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
mShadowBluetoothAdapter.setEnabled(true);
mContext = RuntimeEnvironment.application;
doReturn(mContext).when(mDashboardFragment).getContext();
cachedDevices =
mShadowCachedBluetoothDeviceManager = Shadow.extract(
Utils.getLocalBtManager(mContext).getCachedDeviceManager());
mCachedDevices =
new ArrayList<CachedBluetoothDevice>(new ArrayList<CachedBluetoothDevice>());
mShadowCachedBluetoothDeviceManager.setCachedDevicesCopy(mCachedDevices);
doReturn(mContext).when(mDashboardFragment).getContext();
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mLocalManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
when(mLocalBluetoothProfileManager.getHeadsetProfile()).thenReturn(mHeadsetProfile);
when(mLocalManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
mBluetoothDeviceUpdater = spy(new AvailableMediaBluetoothDeviceUpdater(mDashboardFragment,
mDevicePreferenceCallback, mLocalManager));
mBluetoothDeviceUpdater = spy(new AvailableMediaBluetoothDeviceUpdater(mContext,
mDashboardFragment, mDevicePreferenceCallback));
mBluetoothDeviceUpdater.setPrefContext(mContext);
mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, false);
doNothing().when(mBluetoothDeviceUpdater).addPreference(any());
@@ -110,7 +102,7 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
when(mBluetoothDeviceUpdater.
isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true);
cachedDevices.add(mCachedBluetoothDevice);
mCachedDevices.add(mCachedBluetoothDevice);
mBluetoothDeviceUpdater.onAudioModeChanged();
@@ -123,7 +115,7 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
when(mBluetoothDeviceUpdater.
isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true);
cachedDevices.add(mCachedBluetoothDevice);
mCachedDevices.add(mCachedBluetoothDevice);
mBluetoothDeviceUpdater.onAudioModeChanged();
@@ -136,7 +128,7 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
when(mBluetoothDeviceUpdater.
isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true);
cachedDevices.add(mCachedBluetoothDevice);
mCachedDevices.add(mCachedBluetoothDevice);
mBluetoothDeviceUpdater.onAudioModeChanged();
@@ -149,7 +141,7 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
when(mBluetoothDeviceUpdater.
isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true);
cachedDevices.add(mCachedBluetoothDevice);
mCachedDevices.add(mCachedBluetoothDevice);
mBluetoothDeviceUpdater.onAudioModeChanged();

View File

@@ -34,9 +34,8 @@ import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowAudioManager;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowCachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import org.junit.Before;
import org.junit.Test;
@@ -51,7 +50,8 @@ import java.util.ArrayList;
import java.util.Collection;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {ShadowAudioManager.class, ShadowBluetoothAdapter.class})
@Config(shadows = {ShadowAudioManager.class, ShadowBluetoothAdapter.class,
ShadowCachedBluetoothDeviceManager.class})
public class ConnectedBluetoothDeviceUpdaterTest {
@Mock
private DashboardFragment mDashboardFragment;
@@ -61,16 +61,13 @@ public class ConnectedBluetoothDeviceUpdaterTest {
private CachedBluetoothDevice mCachedBluetoothDevice;
@Mock
private BluetoothDevice mBluetoothDevice;
@Mock
private LocalBluetoothManager mLocalManager;
@Mock
private CachedBluetoothDeviceManager mCachedDeviceManager;
private Context mContext;
private ConnectedBluetoothDeviceUpdater mBluetoothDeviceUpdater;
private Collection<CachedBluetoothDevice> cachedDevices;
private Collection<CachedBluetoothDevice> mCachedDevices;
private ShadowAudioManager mShadowAudioManager;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
private ShadowCachedBluetoothDeviceManager mShadowCachedBluetoothDeviceManager;
@Before
public void setUp() {
@@ -80,16 +77,16 @@ public class ConnectedBluetoothDeviceUpdaterTest {
mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
mShadowBluetoothAdapter.setEnabled(true);
mContext = RuntimeEnvironment.application;
mShadowCachedBluetoothDeviceManager = Shadow.extract(
Utils.getLocalBtManager(mContext).getCachedDeviceManager());
doReturn(mContext).when(mDashboardFragment).getContext();
cachedDevices =
mCachedDevices =
new ArrayList<CachedBluetoothDevice>(new ArrayList<CachedBluetoothDevice>());
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mLocalManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
mBluetoothDeviceUpdater = spy(new ConnectedBluetoothDeviceUpdater(mDashboardFragment,
mDevicePreferenceCallback, mLocalManager));
mShadowCachedBluetoothDeviceManager.setCachedDevicesCopy(mCachedDevices);
mBluetoothDeviceUpdater = spy(new ConnectedBluetoothDeviceUpdater(mContext,
mDashboardFragment, mDevicePreferenceCallback));
mBluetoothDeviceUpdater.setPrefContext(mContext);
doNothing().when(mBluetoothDeviceUpdater).addPreference(any());
doNothing().when(mBluetoothDeviceUpdater).removePreference(any());
@@ -101,7 +98,7 @@ public class ConnectedBluetoothDeviceUpdaterTest {
when(mBluetoothDeviceUpdater.
isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true);
cachedDevices.add(mCachedBluetoothDevice);
mCachedDevices.add(mCachedBluetoothDevice);
mBluetoothDeviceUpdater.onAudioModeChanged();
@@ -114,7 +111,7 @@ public class ConnectedBluetoothDeviceUpdaterTest {
when(mBluetoothDeviceUpdater.
isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isHfpDevice()).thenReturn(true);
cachedDevices.add(mCachedBluetoothDevice);
mCachedDevices.add(mCachedBluetoothDevice);
mBluetoothDeviceUpdater.onAudioModeChanged();
@@ -127,7 +124,7 @@ public class ConnectedBluetoothDeviceUpdaterTest {
when(mBluetoothDeviceUpdater.
isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true);
cachedDevices.add(mCachedBluetoothDevice);
mCachedDevices.add(mCachedBluetoothDevice);
mBluetoothDeviceUpdater.onAudioModeChanged();
@@ -140,7 +137,7 @@ public class ConnectedBluetoothDeviceUpdaterTest {
when(mBluetoothDeviceUpdater.
isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isA2dpDevice()).thenReturn(true);
cachedDevices.add(mCachedBluetoothDevice);
mCachedDevices.add(mCachedBluetoothDevice);
mBluetoothDeviceUpdater.onAudioModeChanged();

View File

@@ -29,9 +29,8 @@ import android.content.Context;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import org.junit.Before;
import org.junit.Test;
@@ -39,8 +38,10 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothAdapter.class})
public class SavedBluetoothDeviceUpdaterTest {
@Mock
@@ -51,10 +52,6 @@ public class SavedBluetoothDeviceUpdaterTest {
private CachedBluetoothDevice mCachedBluetoothDevice;
@Mock
private BluetoothDevice mBluetoothDevice;
@Mock
private LocalBluetoothManager mLocalManager;
@Mock
private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
private Context mContext;
private SavedBluetoothDeviceUpdater mBluetoothDeviceUpdater;
@@ -67,11 +64,10 @@ public class SavedBluetoothDeviceUpdaterTest {
mContext = RuntimeEnvironment.application;
doReturn(mContext).when(mDashboardFragment).getContext();
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mLocalManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
mBluetoothDeviceUpdater = spy(new SavedBluetoothDeviceUpdater(mDashboardFragment,
mDevicePreferenceCallback, mLocalManager));
mBluetoothDeviceUpdater = spy(new SavedBluetoothDeviceUpdater(mContext, mDashboardFragment,
mDevicePreferenceCallback));
mBluetoothDeviceUpdater.setPrefContext(mContext);
mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, false);
doNothing().when(mBluetoothDeviceUpdater).addPreference(any());

View File

@@ -16,7 +16,10 @@
package com.android.settings.core;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEYWORDS;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SEARCHABLE;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
@@ -247,8 +250,7 @@ public class PreferenceXmlParserUtilsTest {
@Test
@Config(qualifiers = "mcc999")
public void extractMetadata_requestIncludesKeywords_shouldContainKeywords()
throws IOException, XmlPullParserException {
public void extractMetadata_requestIncludesKeywords_shouldContainKeywords() throws Exception {
final String expectedKeywords = "a, b, c";
final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
R.xml.location_settings,
@@ -260,6 +262,32 @@ public class PreferenceXmlParserUtilsTest {
assertThat(keywords).isEqualTo(expectedKeywords);
}
@Test
public void extractMetadata_requestSearchable_shouldDefaultToTrue() throws Exception {
final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
R.xml.display_settings, MetadataFlag.FLAG_NEED_SEARCHABLE);
for (Bundle bundle : metadata) {
assertThat(bundle.getBoolean(METADATA_SEARCHABLE)).isTrue();
}
}
@Test
@Config(qualifiers = "mcc999")
public void extractMetadata_requestSearchable_shouldReturnAttributeValue() throws Exception {
final List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(mContext,
R.xml.display_settings,
MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_NEED_SEARCHABLE);
boolean foundKey = false;
for (Bundle bundle : metadata) {
if (TextUtils.equals(bundle.getString(METADATA_KEY), "pref_key_5")) {
assertThat(bundle.getBoolean(METADATA_SEARCHABLE)).isFalse();
foundKey = true;
break;
}
}
assertThat(foundKey).isTrue();
}
/**
* @param resId the ID for the XML preference
* @return an XML resource parser that points to the start tag

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 The Android Open Source Project
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.gestures;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.SharedPreferences;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProviderImpl;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class ReachGesturePreferenceControllerTest {
private static final String KEY_REACH = "gesture_reach";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock
private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
private ReachGesturePreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mController = new ReachGesturePreferenceController(mContext, KEY_REACH);
mController.setConfig(mAmbientDisplayConfiguration);
}
@Test
public void testIsChecked_configIsSet_shouldReturnTrue() {
// Set the setting to be enabled.
when(mAmbientDisplayConfiguration.reachGestureEnabled(anyInt())).thenReturn(true);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void testIsChecked_configIsNotSet_shouldReturnFalse() {
// Set the setting to be disabled.
when(mAmbientDisplayConfiguration.reachGestureEnabled(anyInt())).thenReturn(false);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void getAvailabilityStatus_gestureNotSupported_UNSUPPORTED_ON_DEVICE() {
when(mAmbientDisplayConfiguration.reachGestureAvailable()).thenReturn(false);
final int availabilityStatus = mController.getAvailabilityStatus();
assertThat(availabilityStatus).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_gestureSupported_AVAILABLE() {
when(mAmbientDisplayConfiguration.reachGestureAvailable()).thenReturn(true);
final int availabilityStatus = mController.getAvailabilityStatus();
assertThat(availabilityStatus).isEqualTo(AVAILABLE);
}
@Test
public void isSliceableCorrectKey_returnsTrue() {
final ReachGesturePreferenceController controller =
new ReachGesturePreferenceController(mContext, "gesture_reach");
assertThat(controller.isSliceable()).isTrue();
}
@Test
public void isSliceableIncorrectKey_returnsFalse() {
final ReachGesturePreferenceController controller =
new ReachGesturePreferenceController(mContext, "bad_key");
assertThat(controller.isSliceable()).isFalse();
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.gestures;
import static com.google.common.truth.Truth.assertThat;
import android.provider.SearchIndexableResource;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
public class ReachGestureSettingsTest {
private ReachGestureSettings mSettings;
@Before
public void setUp() {
mSettings = new ReachGestureSettings();
}
@Test
public void testSearchIndexProvider_shouldIndexResource() {
final List<SearchIndexableResource> indexRes =
ReachGestureSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
RuntimeEnvironment.application, true /* enabled */);
assertThat(indexRes).isNotNull();
assertThat(indexRes.get(0).xmlResId).isEqualTo(mSettings.getPreferenceScreenResId());
}
}

View File

@@ -19,13 +19,19 @@ package com.android.settings.homepage;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowThreadUtils;
import org.junit.After;
import org.junit.Before;
@@ -33,18 +39,23 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = ShadowThreadUtils.class)
public class CardContentProviderTest {
private Context mContext;
private CardContentProvider mProvider;
private ContentResolver mResolver;
private Uri mUri;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mProvider = Robolectric.setupContentProvider(CardContentProvider.class);
mProvider = spy(Robolectric.setupContentProvider(CardContentProvider.class));
mResolver = mContext.getContentResolver();
mUri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(CardContentProvider.CARD_AUTHORITY)
@@ -54,6 +65,7 @@ public class CardContentProviderTest {
@After
public void cleanUp() {
ShadowThreadUtils.reset();
CardDatabaseHelper.getInstance(mContext).close();
CardDatabaseHelper.sCardDatabaseHelper = null;
}
@@ -61,7 +73,7 @@ public class CardContentProviderTest {
@Test
public void cardData_insert() {
final int cnt_before_instert = getRowCount();
mContext.getContentResolver().insert(mUri, insertOneRow());
mResolver.insert(mUri, insertOneRow());
final int cnt_after_instert = getRowCount();
assertThat(cnt_after_instert - cnt_before_instert).isEqualTo(1);
@@ -69,7 +81,7 @@ public class CardContentProviderTest {
@Test
public void cardData_query() {
mContext.getContentResolver().insert(mUri, insertOneRow());
mResolver.insert(mUri, insertOneRow());
final int count = getRowCount();
assertThat(count).isGreaterThan(0);
@@ -77,29 +89,27 @@ public class CardContentProviderTest {
@Test
public void cardData_delete() {
final ContentResolver contentResolver = mContext.getContentResolver();
contentResolver.insert(mUri, insertOneRow());
final int del_count = contentResolver.delete(mUri, null, null);
mResolver.insert(mUri, insertOneRow());
final int del_count = mResolver.delete(mUri, null, null);
assertThat(del_count).isGreaterThan(0);
}
@Test
public void cardData_update() {
final ContentResolver contentResolver = mContext.getContentResolver();
contentResolver.insert(mUri, insertOneRow());
mResolver.insert(mUri, insertOneRow());
final double updatingScore= 0.87;
final double updatingScore = 0.87;
final ContentValues values = new ContentValues();
values.put(CardDatabaseHelper.CardColumns.SCORE, updatingScore);
final String strWhere = CardDatabaseHelper.CardColumns.NAME + "=?";
final String[] selectionArgs = {"auto_rotate"};
final int update_count = contentResolver.update(mUri, values, strWhere, selectionArgs);
final int update_count = mResolver.update(mUri, values, strWhere, selectionArgs);
assertThat(update_count).isGreaterThan(0);
final String[] columns = {CardDatabaseHelper.CardColumns.SCORE};
final Cursor cr = contentResolver.query(mUri, columns, strWhere, selectionArgs, null);
final Cursor cr = mResolver.query(mUri, columns, strWhere, selectionArgs, null);
cr.moveToFirst();
final double qryScore = cr.getDouble(0);
@@ -107,6 +117,90 @@ public class CardContentProviderTest {
assertThat(qryScore).isEqualTo(updatingScore);
}
@Test
public void insert_isMainThread_shouldEnableStrictMode() {
ShadowThreadUtils.setIsMainThread(true);
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
mProvider.insert(mUri, insertOneRow());
verify(mProvider).enableStrictMode();
}
@Test
public void query_isMainThread_shouldEnableStrictMode() {
ShadowThreadUtils.setIsMainThread(true);
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
mProvider.query(mUri, null, null, null);
verify(mProvider).enableStrictMode();
}
@Test
public void delete_isMainThread_shouldEnableStrictMode() {
ShadowThreadUtils.setIsMainThread(true);
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
mProvider.delete(mUri, null, null);
verify(mProvider).enableStrictMode();
}
@Test
public void update_isMainThread_shouldEnableStrictMode() {
ShadowThreadUtils.setIsMainThread(true);
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
final ContentValues values = new ContentValues();
values.put(CardDatabaseHelper.CardColumns.SCORE, "0.01");
mProvider.update(mUri, values, null, null);
verify(mProvider).enableStrictMode();
}
@Test
public void insert_notMainThread_shouldNotEnableStrictMode() {
ShadowThreadUtils.setIsMainThread(false);
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
mProvider.insert(mUri, insertOneRow());
verify(mProvider, never()).enableStrictMode();
}
@Test
public void query_notMainThread_shouldNotEnableStrictMode() {
ShadowThreadUtils.setIsMainThread(false);
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
mProvider.query(mUri, null, null, null);
verify(mProvider, never()).enableStrictMode();
}
@Test
public void delete_notMainThread_shouldNotEnableStrictMode() {
ShadowThreadUtils.setIsMainThread(false);
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
mProvider.delete(mUri, null, null);
verify(mProvider, never()).enableStrictMode();
}
@Test
public void update_notMainThread_shouldNotEnableStrictMode() {
ShadowThreadUtils.setIsMainThread(false);
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
final ContentValues values = new ContentValues();
values.put(CardDatabaseHelper.CardColumns.SCORE, "0.01");
mProvider.update(mUri, values, null, null);
verify(mProvider, never()).enableStrictMode();
}
@Test(expected = UnsupportedOperationException.class)
public void getType_shouldCrash() {
mProvider.getType(null);
@@ -138,10 +232,9 @@ public class CardContentProviderTest {
}
private int getRowCount() {
final ContentResolver contentResolver = mContext.getContentResolver();
final Cursor cr = contentResolver.query(mUri, null, null, null);
final Cursor cr = mResolver.query(mUri, null, null, null);
final int count = cr.getCount();
cr.close();
return count;
}
}
}

View File

@@ -17,6 +17,7 @@
package com.android.settings.language;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -25,6 +26,9 @@ import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TtsEngines;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
@@ -38,9 +42,6 @@ import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@RunWith(SettingsRobolectricTestRunner.class)
public class TtsPreferenceControllerTest {
@@ -58,7 +59,8 @@ public class TtsPreferenceControllerTest {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mController = new TtsPreferenceController(mContext, mTtsEngines);
mController = new TtsPreferenceController(mContext, "test_key");
mController.mTtsEngines = mTtsEngines;
mPreference = new Preference(RuntimeEnvironment.application);
mPreference.setKey(mController.getPreferenceKey());
when(mScreen.findPreference(mPreference.getKey())).thenReturn(mPreference);

View File

@@ -169,4 +169,24 @@ public class BaseSearchIndexProviderTest {
assertThat(nonIndexableKeys).contains("status_header");
}
@Test
@Config(qualifiers = "mcc999")
public void getNonIndexableKeys_hasSearchableAttributeInXml_shouldSuppressUnsearchable() {
final BaseSearchIndexProvider provider = new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.display_settings;
return Collections.singletonList(sir);
}
};
final List<String> nonIndexableKeys =
provider.getNonIndexableKeys(RuntimeEnvironment.application);
assertThat(nonIndexableKeys).contains("pref_key_5");
}
}

View File

@@ -1,6 +1,7 @@
package com.android.settings.search;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -21,6 +22,9 @@ import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
public class SettingsSearchIndexablesProviderTest {
@@ -96,16 +100,19 @@ public class SettingsSearchIndexablesProviderTest {
@Test
@Config(qualifiers = "mcc999")
public void testNonIndexablesColumnFetched() {
Uri rawUri = Uri.parse("content://" + BASE_AUTHORITY + "/" +
final Uri rawUri = Uri.parse("content://" + BASE_AUTHORITY + "/" +
SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH);
final Cursor cursor = mProvider.query(rawUri,
SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS, null, null, null);
final List<String> keys = new ArrayList<>();
cursor.moveToFirst();
assertThat(cursor.getCount()).isEqualTo(2);
assertThat(cursor.getString(0)).isEqualTo("pref_key_1");
cursor.moveToNext();
assertThat(cursor.getString(0)).isEqualTo("pref_key_3");
try (Cursor cursor = mProvider.query(rawUri,
SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS, null, null, null)) {
while (cursor.moveToNext()) {
keys.add(cursor.getString(0));
}
}
assertThat(keys).hasSize(3);
assertThat(keys).containsAllOf("pref_key_1", "pref_key_3", "pref_key_5");
}
}

View File

@@ -73,7 +73,7 @@ public class EncryptionAndCredentialTest {
final List<String> expectedKeys = new ArrayList<>();
for (SearchIndexableResource res : index) {
expectedKeys.addAll(((BaseSearchIndexProvider) SEARCH_INDEX_DATA_PROVIDER)
.getNonIndexableKeysFromXml(mContext, res.xmlResId));
.getNonIndexableKeysFromXml(mContext, res.xmlResId, true /* suppressAll */));
}
final List<String> keys = SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);

View File

@@ -168,6 +168,7 @@ public class SliceBroadcastReceiverTest {
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(key)
.build();
verify(resolver).notifyChange(expectedUri, null);
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.android.settings.slices;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.provider.SettingsSlicesContract;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.SliceBroadcastRelay;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class SliceRelayReceiverTest {
private Context mContext;
private SliceRelayReceiver mSliceRelayReceiver;
@Before
public void setUp() {
mContext = spy(RuntimeEnvironment.application);
mSliceRelayReceiver = new SliceRelayReceiver();
}
@Test
public void onReceive_extraUri_notifiesChangeOnUri() {
// Monitor the ContentResolver
final ContentResolver resolver = spy(mContext.getContentResolver());
doReturn(resolver).when(mContext).getContentResolver();
final Uri uri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSlicesContract.AUTHORITY)
.appendPath("path")
.build();
final Intent intent = new Intent();
intent.putExtra(SliceBroadcastRelay.EXTRA_URI, uri.toString());
mSliceRelayReceiver.onReceive(mContext, intent);
verify(resolver).notifyChange(eq(uri), any());
}
}

View File

@@ -1,15 +1,16 @@
package com.android.settings.testutils;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
import static com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag
.FLAG_INCLUDE_PREF_SCREEN;
import static com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag.FLAG_NEED_KEY;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Xml;
import com.android.settings.core.PreferenceXmlParserUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.util.ArrayList;
@@ -25,30 +26,21 @@ public class XmlTestUtils {
* on the screen.
*
* @param context of the preference screen.
* @param xmlId of the Preference Xml to be parsed.
* @param xmlId of the Preference Xml to be parsed.
* @return List of all keys in the preference Xml
*/
public static List<String> getKeysFromPreferenceXml(Context context, int xmlId) {
final XmlResourceParser parser = context.getResources().getXml(xmlId);
final AttributeSet attrs = Xml.asAttributeSet(parser);
final List<String> keys = new ArrayList<>();
String key;
try {
while (parser.next() != XmlPullParser.END_DOCUMENT) {
try {
key = PreferenceXmlParserUtils.getDataKey(context, attrs);
if (!TextUtils.isEmpty(key)) {
keys.add(key);
}
} catch (NullPointerException e) {
continue;
} catch (Resources.NotFoundException e) {
continue;
List<Bundle> metadata = PreferenceXmlParserUtils.extractMetadata(context, xmlId,
FLAG_NEED_KEY | FLAG_INCLUDE_PREF_SCREEN);
for (Bundle bundle : metadata) {
final String key = bundle.getString(METADATA_KEY);
if (!TextUtils.isEmpty(key)) {
keys.add(key);
}
}
} catch (java.io.IOException e) {
return null;
} catch (XmlPullParserException e) {
} catch (java.io.IOException | XmlPullParserException e) {
return null;
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.testutils.shadow;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.Collection;
/**
* Shadow class for {@link CachedBluetoothDeviceManager} to allow tests to manages the set of
* remote Bluetooth devices.
*/
@Implements(CachedBluetoothDeviceManager.class)
public class ShadowCachedBluetoothDeviceManager {
private Collection<CachedBluetoothDevice> mCachedDevices;
public void setCachedDevicesCopy(Collection<CachedBluetoothDevice> cachedDevices) {
mCachedDevices = cachedDevices;
}
@Implementation
public synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() {
return mCachedDevices;
}
}

View File

@@ -64,6 +64,7 @@ import androidx.slice.SliceProvider;
import androidx.slice.core.SliceAction;
import androidx.slice.core.SliceQuery;
import androidx.slice.widget.ListContent;
import androidx.slice.widget.SliceContent;
import androidx.slice.widget.RowContent;
import androidx.slice.widget.SliceLiveData;
@@ -367,31 +368,27 @@ public class WifiCallingSliceHelperTest {
// Get all the rows
final ListContent listContent = new ListContent(mContext, slice);
final ArrayList<SliceItem> rowItems = listContent.getRowItems();
final ArrayList<SliceContent> rowItems = listContent.getRowItems();
assertThat(rowItems.size()).isEqualTo(4 /* 4 items including header */);
// First row is HEADER
SliceItem rowSliceItem = rowItems.get(0);
RowContent rowContent = new RowContent(mContext, rowSliceItem, true);
RowContent rowContent = (RowContent) rowItems.get(0);
assertThat(rowContent.getTitleItem().getText()).isEqualTo(mContext.getText(
R.string.wifi_calling_mode_title));
// next is WIFI_ONLY
rowSliceItem = rowItems.get(1);
rowContent = new RowContent(mContext, rowSliceItem, false);
rowContent = (RowContent) rowItems.get(1);
assertThat(rowContent.getTitleItem().getText()).isEqualTo(mContext.getText(
com.android.internal.R.string.wfc_mode_wifi_only_summary));
// next is WIFI_PREFERRED
rowSliceItem = rowItems.get(2);
rowContent = new RowContent(mContext, rowSliceItem, false);
rowContent = (RowContent) rowItems.get(2);
assertThat(rowContent.getTitleItem().getText()).isEqualTo(mContext.getText(
com.android.internal.R.string.wfc_mode_wifi_preferred_summary));
// next is CELLULAR_PREFERRED
rowSliceItem = rowItems.get(3);
rowContent = new RowContent(mContext, rowSliceItem, false);
rowContent = (RowContent) rowItems.get(3);
assertThat(rowContent.getTitleItem().getText()).isEqualTo(mContext.getText(
com.android.internal.R.string.wfc_mode_cellular_preferred_summary));