Snap for 4963158 from 6fdf8c225d to qt-release
Change-Id: I79abaef7f6b4b49918bb9ae74d07369c57b29abe
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 ".", 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.
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.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <color name="face_anim_particle_color_1">#ff00bcd4</color> <!-- 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.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <color name="face_anim_particle_color_2">#ffef6c00</color> <!-- 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.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <color name="face_anim_particle_color_3">#ff4caf50</color> <!-- 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.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <color name="face_anim_particle_color_4">#fffdd835</color> <!-- 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.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <color name="face_anim_particle_error">#ff9e9e9e</color> <!-- 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>
|
||||
|
||||
|
||||
@@ -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} -->
|
||||
|
||||
@@ -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] -->
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
37
res/xml/reach_gesture_settings.xml
Normal file
37
res/xml/reach_gesture_settings.xml
Normal 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>
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class BackupSettingsActivityPreferenceController extends BasePreferenceCo
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return mUm.isAdminUser()
|
||||
? AVAILABLE
|
||||
? AVAILABLE_UNSEARCHABLE
|
||||
: UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
81
src/com/android/settings/gestures/ReachGestureSettings.java
Normal file
81
src/com/android/settings/gestures/ReachGestureSettings.java
Normal 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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
39
src/com/android/settings/slices/SliceRelayReceiver.java
Normal file
39
src/com/android/settings/slices/SliceRelayReceiver.java
Normal 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 */);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -168,6 +168,7 @@ public class SliceBroadcastReceiverTest {
|
||||
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
|
||||
.appendPath(key)
|
||||
.build();
|
||||
|
||||
verify(resolver).notifyChange(expectedUri, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user