Merge "Fix a bug where device index is not skipped correct." into pi-dev
diff --git a/res/layout/storage_summary_donut.xml b/res/layout/storage_summary_donut.xml
index ce7e272..b183b2e 100644
--- a/res/layout/storage_summary_donut.xml
+++ b/res/layout/storage_summary_donut.xml
@@ -17,7 +17,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="?android:attr/colorSecondary"
+ android:background="?android:attr/colorPrimary"
android:gravity="center_vertical"
android:orientation="horizontal" >
diff --git a/res/raw/gesture_swipe_up.mp4 b/res/raw/gesture_swipe_up.mp4
index f4c8fd1..2f65292 100644
--- a/res/raw/gesture_swipe_up.mp4
+++ b/res/raw/gesture_swipe_up.mp4
Binary files differ
diff --git a/res/values/config.xml b/res/values/config.xml
index 8e55ea9..f46134f 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -134,4 +134,9 @@
<!-- Whether or not to show the night light suggestion. -->
<bool name="config_night_light_suggestion_enabled">true</bool>
+ <!-- Whether or not the device is capable of multiple levels of vibration intensity.
+ Note that this is different from whether it can control the vibration amplitude as some
+ devices will be able to vary their amplitude but do not possess enough dynamic range to
+ have distinct intensity levels -->
+ <bool name="config_vibration_supports_multiple_intensities">false</bool>
</resources>
diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml
index 213ff1c..3dac8b8 100644
--- a/res/xml/my_device_info.xml
+++ b/res/xml/my_device_info.xml
@@ -19,8 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="my_device_info_pref_screen"
- android:title="@string/about_settings"
- settings:initialExpandedChildrenCount="7">
+ android:title="@string/about_settings">
<com.android.settings.applications.LayoutPreference
android:key="my_device_info_header"
diff --git a/res/xml/smart_battery_detail.xml b/res/xml/smart_battery_detail.xml
index e1246ed..8af3e96 100644
--- a/res/xml/smart_battery_detail.xml
+++ b/res/xml/smart_battery_detail.xml
@@ -30,6 +30,7 @@
android:key="smart_battery"
android:title="@string/smart_battery_title"
android:summary="@string/smart_battery_summary"
+ settings:controller="com.android.settings.fuelgauge.SmartBatteryPreferenceController"
settings:allowDividerAbove="true"/>
<SwitchPreference
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 72e485e..4ddcc31 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -779,17 +779,27 @@
}
private String getVibrationSummary(Context context, @VibrationIntensity int intensity) {
- switch (intensity) {
- case Vibrator.VIBRATION_INTENSITY_OFF:
- return context.getString(R.string.accessibility_vibration_summary_off);
- case Vibrator.VIBRATION_INTENSITY_LOW:
- return context.getString(R.string.accessibility_vibration_summary_low);
- case Vibrator.VIBRATION_INTENSITY_MEDIUM:
- return context.getString(R.string.accessibility_vibration_summary_medium);
- case Vibrator.VIBRATION_INTENSITY_HIGH:
- return context.getString(R.string.accessibility_vibration_summary_high);
- default:
- return "";
+ final boolean supportsMultipleIntensities = context.getResources().getBoolean(
+ R.bool.config_vibration_supports_multiple_intensities);
+ if (supportsMultipleIntensities) {
+ switch (intensity) {
+ case Vibrator.VIBRATION_INTENSITY_OFF:
+ return context.getString(R.string.accessibility_vibration_summary_off);
+ case Vibrator.VIBRATION_INTENSITY_LOW:
+ return context.getString(R.string.accessibility_vibration_summary_low);
+ case Vibrator.VIBRATION_INTENSITY_MEDIUM:
+ return context.getString(R.string.accessibility_vibration_summary_medium);
+ case Vibrator.VIBRATION_INTENSITY_HIGH:
+ return context.getString(R.string.accessibility_vibration_summary_high);
+ default:
+ return "";
+ }
+ } else {
+ if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+ return context.getString(R.string.switch_on_text);
+ } else {
+ return context.getString(R.string.switch_off_text);
+ }
}
}
diff --git a/src/com/android/settings/accessibility/MagnificationGesturesPreferenceController.java b/src/com/android/settings/accessibility/MagnificationGesturesPreferenceController.java
index 603b698..bb75814 100644
--- a/src/com/android/settings/accessibility/MagnificationGesturesPreferenceController.java
+++ b/src/com/android/settings/accessibility/MagnificationGesturesPreferenceController.java
@@ -17,6 +17,7 @@
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.preference.Preference;
+import android.text.TextUtils;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
@@ -62,6 +63,12 @@
}
@Override
+ public boolean isSliceable() {
+ return TextUtils.equals(getPreferenceKey(),
+ "screen_magnification_gestures_preference_screen");
+ }
+
+ @Override
public CharSequence getSummary() {
int resId = 0;
if (mIsFromSUW) {
diff --git a/src/com/android/settings/accessibility/MagnificationNavbarPreferenceController.java b/src/com/android/settings/accessibility/MagnificationNavbarPreferenceController.java
index 9c6301b..ef71412 100644
--- a/src/com/android/settings/accessibility/MagnificationNavbarPreferenceController.java
+++ b/src/com/android/settings/accessibility/MagnificationNavbarPreferenceController.java
@@ -17,6 +17,7 @@
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.preference.Preference;
+import android.text.TextUtils;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
@@ -69,6 +70,12 @@
}
@Override
+ public boolean isSliceable() {
+ return TextUtils.equals(getPreferenceKey(),
+ "screen_magnification_navbar_preference_screen");
+ }
+
+ @Override
public CharSequence getSummary() {
int resId = 0;
if (mIsFromSUW) {
diff --git a/src/com/android/settings/accessibility/NotificationVibrationPreferenceFragment.java b/src/com/android/settings/accessibility/NotificationVibrationPreferenceFragment.java
index 6340bb1..5f43c2d 100644
--- a/src/com/android/settings/accessibility/NotificationVibrationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/NotificationVibrationPreferenceFragment.java
@@ -15,7 +15,9 @@
*/
package com.android.settings.accessibility;
+import android.media.AudioAttributes;
import android.os.Vibrator;
+import android.os.VibrationEffect;
import android.provider.Settings;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -44,6 +46,11 @@
}
@Override
+ protected int getPreviewVibrationAudioAttributesUsage() {
+ return AudioAttributes.USAGE_NOTIFICATION;
+ }
+
+ @Override
protected int getDefaultVibrationIntensity() {
Vibrator vibrator = getContext().getSystemService(Vibrator.class);
return vibrator.getDefaultNotificationVibrationIntensity();
diff --git a/src/com/android/settings/accessibility/OWNERS b/src/com/android/settings/accessibility/OWNERS
index 28dfdef..ba03055 100644
--- a/src/com/android/settings/accessibility/OWNERS
+++ b/src/com/android/settings/accessibility/OWNERS
@@ -1,3 +1,6 @@
# Default reviewers for this and subdirectories.
pweaver@google.com
-zork@google.com
\ No newline at end of file
+zork@google.com
+
+per-file HapticFeedbackIntensityPreferenceController.java = michaelwr@google.com
+per-file *Vibration* = michaelwr@google.com
diff --git a/src/com/android/settings/accessibility/TouchVibrationPreferenceFragment.java b/src/com/android/settings/accessibility/TouchVibrationPreferenceFragment.java
index ea36833..1d20124 100644
--- a/src/com/android/settings/accessibility/TouchVibrationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/TouchVibrationPreferenceFragment.java
@@ -16,7 +16,9 @@
package com.android.settings.accessibility;
import android.graphics.drawable.Drawable;
+import android.media.AudioAttributes;
import android.os.Vibrator;
+import android.os.VibrationEffect;
import android.provider.Settings;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -51,6 +53,11 @@
}
@Override
+ protected int getPreviewVibrationAudioAttributesUsage() {
+ return AudioAttributes.USAGE_ASSISTANCE_SONIFICATION;
+ }
+
+ @Override
public void onVibrationIntensitySelected(int intensity) {
// We want to keep HAPTIC_FEEDBACK_ENABLED consistent with this setting since some
// applications check it directly before triggering their own haptic feedback.
diff --git a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java
index 9c81afa..3fbb123 100644
--- a/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java
+++ b/src/com/android/settings/accessibility/VibrationIntensityPreferenceController.java
@@ -81,17 +81,27 @@
}
public static CharSequence getIntensityString(Context context, int intensity) {
- switch (intensity) {
- case Vibrator.VIBRATION_INTENSITY_OFF:
- return context.getText(R.string.accessibility_vibration_intensity_off);
- case Vibrator.VIBRATION_INTENSITY_LOW:
- return context.getText(R.string.accessibility_vibration_intensity_low);
- case Vibrator.VIBRATION_INTENSITY_MEDIUM:
- return context.getText(R.string.accessibility_vibration_intensity_medium);
- case Vibrator.VIBRATION_INTENSITY_HIGH:
- return context.getText(R.string.accessibility_vibration_intensity_high);
- default:
- return "";
+ final boolean supportsMultipleIntensities = context.getResources().getBoolean(
+ R.bool.config_vibration_supports_multiple_intensities);
+ if (supportsMultipleIntensities) {
+ switch (intensity) {
+ case Vibrator.VIBRATION_INTENSITY_OFF:
+ return context.getString(R.string.accessibility_vibration_intensity_off);
+ case Vibrator.VIBRATION_INTENSITY_LOW:
+ return context.getString(R.string.accessibility_vibration_intensity_low);
+ case Vibrator.VIBRATION_INTENSITY_MEDIUM:
+ return context.getString(R.string.accessibility_vibration_intensity_medium);
+ case Vibrator.VIBRATION_INTENSITY_HIGH:
+ return context.getString(R.string.accessibility_vibration_intensity_high);
+ default:
+ return "";
+ }
+ } else {
+ if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+ return context.getString(R.string.switch_off_text);
+ } else {
+ return context.getString(R.string.switch_on_text);
+ }
}
}
diff --git a/src/com/android/settings/accessibility/VibrationPreferenceFragment.java b/src/com/android/settings/accessibility/VibrationPreferenceFragment.java
index e911b61..b92aac2 100644
--- a/src/com/android/settings/accessibility/VibrationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/VibrationPreferenceFragment.java
@@ -21,8 +21,10 @@
import android.content.Context;
import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
+import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Handler;
+import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings;
import android.util.ArrayMap;
@@ -53,28 +55,15 @@
final static String KEY_INTENSITY_MEDIUM = "intensity_medium";
@VisibleForTesting
final static String KEY_INTENSITY_HIGH = "intensity_high";
+ // KEY_INTENSITY_ON is only used when the device doesn't support multiple intensity levels.
+ @VisibleForTesting
+ final static String KEY_INTENSITY_ON = "intensity_on";
private final Map<String, VibrationIntensityCandidateInfo> mCandidates;
private final SettingsObserver mSettingsObserver;
public VibrationPreferenceFragment() {
mCandidates = new ArrayMap<>();
- mCandidates.put(KEY_INTENSITY_OFF,
- new VibrationIntensityCandidateInfo(KEY_INTENSITY_OFF,
- R.string.accessibility_vibration_intensity_off,
- Vibrator.VIBRATION_INTENSITY_OFF));
- mCandidates.put(KEY_INTENSITY_LOW,
- new VibrationIntensityCandidateInfo(KEY_INTENSITY_LOW,
- R.string.accessibility_vibration_intensity_low,
- Vibrator.VIBRATION_INTENSITY_LOW));
- mCandidates.put(KEY_INTENSITY_MEDIUM,
- new VibrationIntensityCandidateInfo(KEY_INTENSITY_MEDIUM,
- R.string.accessibility_vibration_intensity_medium,
- Vibrator.VIBRATION_INTENSITY_MEDIUM));
- mCandidates.put(KEY_INTENSITY_HIGH,
- new VibrationIntensityCandidateInfo(KEY_INTENSITY_HIGH,
- R.string.accessibility_vibration_intensity_high,
- Vibrator.VIBRATION_INTENSITY_HIGH));
mSettingsObserver = new SettingsObserver();
}
@@ -82,6 +71,39 @@
public void onAttach(Context context) {
super.onAttach(context);
mSettingsObserver.register();
+ if (mCandidates.isEmpty()) {
+ loadCandidates(context);
+ }
+ }
+
+ private void loadCandidates(Context context) {
+ final boolean supportsMultipleIntensities = context.getResources().getBoolean(
+ R.bool.config_vibration_supports_multiple_intensities);
+ if (supportsMultipleIntensities) {
+ mCandidates.put(KEY_INTENSITY_OFF,
+ new VibrationIntensityCandidateInfo(KEY_INTENSITY_OFF,
+ R.string.accessibility_vibration_intensity_off,
+ Vibrator.VIBRATION_INTENSITY_OFF));
+ mCandidates.put(KEY_INTENSITY_LOW,
+ new VibrationIntensityCandidateInfo(KEY_INTENSITY_LOW,
+ R.string.accessibility_vibration_intensity_low,
+ Vibrator.VIBRATION_INTENSITY_LOW));
+ mCandidates.put(KEY_INTENSITY_MEDIUM,
+ new VibrationIntensityCandidateInfo(KEY_INTENSITY_MEDIUM,
+ R.string.accessibility_vibration_intensity_medium,
+ Vibrator.VIBRATION_INTENSITY_MEDIUM));
+ mCandidates.put(KEY_INTENSITY_HIGH,
+ new VibrationIntensityCandidateInfo(KEY_INTENSITY_HIGH,
+ R.string.accessibility_vibration_intensity_high,
+ Vibrator.VIBRATION_INTENSITY_HIGH));
+ } else {
+ mCandidates.put(KEY_INTENSITY_OFF,
+ new VibrationIntensityCandidateInfo(KEY_INTENSITY_OFF,
+ R.string.switch_off_text, Vibrator.VIBRATION_INTENSITY_OFF));
+ mCandidates.put(KEY_INTENSITY_ON,
+ new VibrationIntensityCandidateInfo(KEY_INTENSITY_ON,
+ R.string.switch_on_text, getDefaultVibrationIntensity()));
+ }
}
@Override
@@ -105,6 +127,24 @@
*/
protected void onVibrationIntensitySelected(int intensity) { }
+ /**
+ * Play a vibration effect with intensity just selected by user
+ */
+ protected void playVibrationPreview() {
+ Vibrator vibrator = getContext().getSystemService(Vibrator.class);
+ VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
+ AudioAttributes.Builder builder = new AudioAttributes.Builder();
+ builder.setUsage(getPreviewVibrationAudioAttributesUsage());
+ vibrator.vibrate(effect, builder.build());
+ }
+
+ /**
+ * Get the AudioAttributes usage for vibration preview.
+ */
+ protected int getPreviewVibrationAudioAttributesUsage() {
+ return AudioAttributes.USAGE_UNKNOWN;
+ }
+
@Override
protected List<? extends CandidateInfo> getCandidates() {
List<VibrationIntensityCandidateInfo> candidates = new ArrayList<>(mCandidates.values());
@@ -118,7 +158,10 @@
final int vibrationIntensity = Settings.System.getInt(getContext().getContentResolver(),
getVibrationIntensitySetting(), getDefaultVibrationIntensity());
for (VibrationIntensityCandidateInfo candidate : mCandidates.values()) {
- if (candidate.getIntensity() == vibrationIntensity) {
+ final boolean matchesIntensity = candidate.getIntensity() == vibrationIntensity;
+ final boolean matchesOn = candidate.getKey().equals(KEY_INTENSITY_ON)
+ && vibrationIntensity != Vibrator.VIBRATION_INTENSITY_OFF;
+ if (matchesIntensity || matchesOn) {
return candidate.getKey();
}
}
@@ -189,6 +232,7 @@
@Override
public void onChange(boolean selfChange, Uri uri) {
updateCandidates();
+ playVibrationPreview();
}
}
}
diff --git a/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java b/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
index da759a3..f01efad 100644
--- a/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
+++ b/src/com/android/settings/bluetooth/BluetoothSliceBuilder.java
@@ -17,8 +17,6 @@
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
-import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
-
import android.annotation.ColorInt;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
@@ -28,6 +26,7 @@
import android.content.IntentFilter;
import android.net.Uri;
import android.provider.SettingsSlicesContract;
+import android.support.v4.graphics.drawable.IconCompat;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
@@ -42,8 +41,6 @@
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.SliceAction;
-import android.support.v4.graphics.drawable.IconCompat;
-
public class BluetoothSliceBuilder {
private static final String TAG = "BluetoothSliceBuilder";
@@ -71,7 +68,8 @@
INTENT_FILTER.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
}
- private BluetoothSliceBuilder() {}
+ private BluetoothSliceBuilder() {
+ }
/**
* Return a Bluetooth Slice bound to {@link #BLUETOOTH_URI}.
@@ -80,7 +78,7 @@
* Bluetooth.
*/
public static Slice getSlice(Context context) {
- final boolean isBluetoothEnabled = isBluetoothEnabled(context);
+ final boolean isBluetoothEnabled = isBluetoothEnabled();
final CharSequence title = context.getText(R.string.bluetooth_settings);
final IconCompat icon = IconCompat.createWithResource(context,
R.drawable.ic_settings_bluetooth);
@@ -100,6 +98,17 @@
.build();
}
+ public static Intent getIntent(Context context) {
+ final String screenTitle = context.getText(R.string.bluetooth_settings_title).toString();
+ final Uri contentUri = new Uri.Builder().appendPath(
+ SettingsSlicesContract.KEY_BLUETOOTH).build();
+ return DatabaseIndexingUtils.buildSearchResultPageIntent(context,
+ BluetoothDashboardFragment.class.getName(), null /* key */, screenTitle,
+ MetricsProto.MetricsEvent.SETTINGS_CONNECTED_DEVICE_CATEGORY)
+ .setClassName(context.getPackageName(), SubSettings.class.getName())
+ .setData(contentUri);
+ }
+
/**
* Update the current Bluetooth status to the boolean value keyed by
* {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
@@ -115,22 +124,13 @@
// handle it.
}
- private static boolean isBluetoothEnabled(Context context) {
- final LocalBluetoothAdapter adapter = LocalBluetoothManager.getInstance(context,
- null /* callback */).getBluetoothAdapter();
+ private static boolean isBluetoothEnabled() {
+ final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
return adapter.isEnabled();
}
private static PendingIntent getPrimaryAction(Context context) {
- final String screenTitle = context.getText(R.string.bluetooth_settings_title).toString();
- final Uri contentUri = new Uri.Builder().appendPath(
- SettingsSlicesContract.KEY_BLUETOOTH).build();
- final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
- BluetoothDashboardFragment.class.getName(), null /* key */, screenTitle,
- MetricsProto.MetricsEvent.SETTINGS_CONNECTED_DEVICE_CATEGORY)
- .setClassName(context.getPackageName(), SubSettings.class.getName())
- .setData(contentUri);
-
+ final Intent intent = getIntent(context);
return PendingIntent.getActivity(context, 0 /* requestCode */,
intent, 0 /* flags */);
}
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 8e56b12..e8f9771 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -57,14 +57,12 @@
import java.util.Arrays;
import java.util.List;
-public class StorageDashboardFragment extends DashboardFragment
- implements
+public class StorageDashboardFragment extends DashboardFragment implements
LoaderManager.LoaderCallbacks<SparseArray<StorageAsyncLoader.AppsStorageResult>> {
private static final String TAG = "StorageDashboardFrag";
private static final int STORAGE_JOB_ID = 0;
private static final int ICON_JOB_ID = 1;
private static final int VOLUME_SIZE_JOB_ID = 2;
- private static final int OPTIONS_MENU_MIGRATE_DATA = 100;
private VolumeInfo mVolume;
private PrivateStorageInfo mStorageInfo;
diff --git a/src/com/android/settings/fuelgauge/SmartBatteryPreferenceController.java b/src/com/android/settings/fuelgauge/SmartBatteryPreferenceController.java
index 3e80c35..8b7cde8 100644
--- a/src/com/android/settings/fuelgauge/SmartBatteryPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/SmartBatteryPreferenceController.java
@@ -21,6 +21,7 @@
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
+import android.text.TextUtils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
@@ -49,6 +50,11 @@
}
@Override
+ public boolean isSliceable() {
+ return TextUtils.equals(getPreferenceKey(), "smart_battery");
+ }
+
+ @Override
public void updateState(Preference preference) {
super.updateState(preference);
final boolean smartBatteryOn = Settings.Global.getInt(mContext.getContentResolver(),
diff --git a/src/com/android/settings/location/LocationSliceBuilder.java b/src/com/android/settings/location/LocationSliceBuilder.java
index e69ccfb..4cf861f 100644
--- a/src/com/android/settings/location/LocationSliceBuilder.java
+++ b/src/com/android/settings/location/LocationSliceBuilder.java
@@ -79,15 +79,18 @@
.build();
}
- private static PendingIntent getPrimaryAction(Context context) {
+ public static Intent getIntent(Context context) {
final String screenTitle = context.getText(R.string.location_settings_title).toString();
final Uri contentUri = new Uri.Builder().appendPath(KEY_LOCATION).build();
- final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
+ return DatabaseIndexingUtils.buildSearchResultPageIntent(context,
LocationSettings.class.getName(), KEY_LOCATION, screenTitle,
MetricsEvent.LOCATION)
.setClassName(context.getPackageName(), SubSettings.class.getName())
.setData(contentUri);
+ }
+ private static PendingIntent getPrimaryAction(Context context) {
+ final Intent intent = getIntent(context);
return PendingIntent.getActivity(context, 0 /* requestCode */,
intent, 0 /* flags */);
}
diff --git a/src/com/android/settings/notification/AlarmVolumePreferenceController.java b/src/com/android/settings/notification/AlarmVolumePreferenceController.java
index 3c238aa..92a1e90 100644
--- a/src/com/android/settings/notification/AlarmVolumePreferenceController.java
+++ b/src/com/android/settings/notification/AlarmVolumePreferenceController.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.media.AudioManager;
+import android.text.TextUtils;
import com.android.settings.R;
@@ -37,6 +38,11 @@
}
@Override
+ public boolean isSliceable() {
+ return TextUtils.equals(getPreferenceKey(), "alarm_volume");
+ }
+
+ @Override
public String getPreferenceKey() {
return KEY_ALARM_VOLUME;
}
diff --git a/src/com/android/settings/notification/ZenModeSliceBuilder.java b/src/com/android/settings/notification/ZenModeSliceBuilder.java
index aedd0b3..16591ce 100644
--- a/src/com/android/settings/notification/ZenModeSliceBuilder.java
+++ b/src/com/android/settings/notification/ZenModeSliceBuilder.java
@@ -123,6 +123,16 @@
// handle it.
}
+ public static Intent getIntent(Context context) {
+ final Uri contentUri = new Uri.Builder().appendPath(ZEN_MODE_KEY).build();
+ final String screenTitle = context.getText(R.string.zen_mode_settings_title).toString();
+ return DatabaseIndexingUtils.buildSearchResultPageIntent(context,
+ ZenModeSettings.class.getName(), ZEN_MODE_KEY, screenTitle,
+ MetricsEvent.NOTIFICATION_ZEN_MODE)
+ .setClassName(context.getPackageName(), SubSettings.class.getName())
+ .setData(contentUri);
+ }
+
private static boolean isZenModeEnabled(Context context) {
final NotificationManager manager = context.getSystemService(NotificationManager.class);
final int zenMode = manager.getZenMode();
@@ -139,16 +149,8 @@
}
private static PendingIntent getPrimaryAction(Context context) {
- final String screenTitle = context.getText(R.string.zen_mode_settings_title).toString();
- final Uri contentUri = new Uri.Builder().appendPath(ZEN_MODE_KEY).build();
- final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
- ZenModeSettings.class.getName(), ZEN_MODE_KEY, screenTitle,
- MetricsEvent.NOTIFICATION_ZEN_MODE)
- .setClassName(context.getPackageName(), SubSettings.class.getName())
- .setData(contentUri);
-
- return PendingIntent.getActivity(context, 0 /* requestCode */,
- intent, 0 /* flags */);
+ final Intent intent = getIntent(context);
+ return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */);
}
private static PendingIntent getBroadcastIntent(Context context) {
diff --git a/src/com/android/settings/search/DeviceIndexUpdateJobService.java b/src/com/android/settings/search/DeviceIndexUpdateJobService.java
index 97b0a61..3eb9041 100644
--- a/src/com/android/settings/search/DeviceIndexUpdateJobService.java
+++ b/src/com/android/settings/search/DeviceIndexUpdateJobService.java
@@ -38,8 +38,8 @@
import androidx.slice.Slice;
import androidx.slice.SliceItem;
-import androidx.slice.SliceManager;
-import androidx.slice.SliceManager.SliceCallback;
+import androidx.slice.SliceViewManager;
+import androidx.slice.SliceViewManager.SliceCallback;
import androidx.slice.SliceMetadata;
import androidx.slice.core.SliceQuery;
import androidx.slice.widget.ListContent;
@@ -80,7 +80,7 @@
}
final DeviceIndexFeatureProvider indexProvider = FeatureFactory.getFactory(this)
.getDeviceIndexFeatureProvider();
- final SliceManager manager = getSliceManager();
+ final SliceViewManager manager = getSliceViewManager();
final Uri baseUri = new Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
@@ -124,8 +124,8 @@
jobFinished(params, false);
}
- protected SliceManager getSliceManager() {
- return SliceManager.getInstance(this);
+ protected SliceViewManager getSliceViewManager() {
+ return SliceViewManager.getInstance(this);
}
protected SliceMetadata getMetadata(Slice loadedSlice) {
@@ -158,7 +158,7 @@
return null;
}
- protected Slice bindSliceSynchronous(SliceManager manager, Uri slice) {
+ protected Slice bindSliceSynchronous(SliceViewManager manager, Uri slice) {
final Slice[] returnSlice = new Slice[1];
CountDownLatch latch = new CountDownLatch(1);
SliceCallback callback = new SliceCallback() {
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 47736df..841247b 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -23,23 +23,23 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
+import android.os.StrictMode;
import android.provider.Settings;
import android.provider.SettingsSlicesContract;
import android.support.annotation.VisibleForTesting;
-import android.support.v4.graphics.drawable.IconCompat;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.KeyValueListParser;
import android.util.Log;
import android.util.Pair;
-import com.android.settings.location.LocationSliceBuilder;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.bluetooth.BluetoothSliceBuilder;
import com.android.settings.core.BasePreferenceController;
+import com.android.settings.location.LocationSliceBuilder;
+import com.android.settings.notification.ZenModeSliceBuilder;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settings.wifi.WifiSliceBuilder;
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
-import com.android.settings.bluetooth.BluetoothSliceBuilder;
-import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settingslib.SliceBroadcastRelay;
import com.android.settingslib.utils.ThreadUtils;
@@ -150,7 +150,7 @@
@Override
public void onSlicePinned(Uri sliceUri) {
if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) {
- registerIntentToUri(WifiSliceBuilder.INTENT_FILTER , sliceUri);
+ registerIntentToUri(WifiSliceBuilder.INTENT_FILTER, sliceUri);
return;
} else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
registerIntentToUri(ZenModeSliceBuilder.INTENT_FILTER, sliceUri);
@@ -176,41 +176,51 @@
@Override
public Slice onBindSlice(Uri sliceUri) {
- final Set<String> blockedKeys = getBlockedKeys();
- final String key = sliceUri.getLastPathSegment();
- if (blockedKeys.contains(key)) {
- Log.e(TAG, "Requested blocked slice with Uri: " + sliceUri);
- return null;
- }
+ final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
+ try {
+ if (!ThreadUtils.isMainThread()) {
+ StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
+ .permitAll()
+ .build());
+ }
+ final Set<String> blockedKeys = getBlockedKeys();
+ final String key = sliceUri.getLastPathSegment();
+ if (blockedKeys.contains(key)) {
+ Log.e(TAG, "Requested blocked slice with Uri: " + sliceUri);
+ return null;
+ }
- // If adding a new Slice, do not directly match Slice URIs.
- // Use {@link SlicesDatabaseAccessor}.
- if (WifiCallingSliceHelper.WIFI_CALLING_URI.equals(sliceUri)) {
- return FeatureFactory.getFactory(getContext())
- .getSlicesFeatureProvider()
- .getNewWifiCallingSliceHelper(getContext())
- .createWifiCallingSlice(sliceUri);
- } else if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) {
- return WifiSliceBuilder.getSlice(getContext());
- } else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
- return ZenModeSliceBuilder.getSlice(getContext());
- } else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
- return BluetoothSliceBuilder.getSlice(getContext());
- } else if (LocationSliceBuilder.LOCATION_URI.equals(sliceUri)) {
- return LocationSliceBuilder.getSlice(getContext());
- }
+ // If adding a new Slice, do not directly match Slice URIs.
+ // Use {@link SlicesDatabaseAccessor}.
+ if (WifiCallingSliceHelper.WIFI_CALLING_URI.equals(sliceUri)) {
+ return FeatureFactory.getFactory(getContext())
+ .getSlicesFeatureProvider()
+ .getNewWifiCallingSliceHelper(getContext())
+ .createWifiCallingSlice(sliceUri);
+ } else if (WifiSliceBuilder.WIFI_URI.equals(sliceUri)) {
+ return WifiSliceBuilder.getSlice(getContext());
+ } else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(sliceUri)) {
+ return ZenModeSliceBuilder.getSlice(getContext());
+ } else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(sliceUri)) {
+ return BluetoothSliceBuilder.getSlice(getContext());
+ } else if (LocationSliceBuilder.LOCATION_URI.equals(sliceUri)) {
+ return LocationSliceBuilder.getSlice(getContext());
+ }
- SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri);
- if (cachedSliceData == null) {
- loadSliceInBackground(sliceUri);
- return getSliceStub(sliceUri);
- }
+ SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri);
+ if (cachedSliceData == null) {
+ loadSliceInBackground(sliceUri);
+ return getSliceStub(sliceUri);
+ }
- // Remove the SliceData from the cache after it has been used to prevent a memory-leak.
- if (!mSliceDataCache.containsKey(sliceUri)) {
- mSliceWeakDataCache.remove(sliceUri);
+ // Remove the SliceData from the cache after it has been used to prevent a memory-leak.
+ if (!mSliceDataCache.containsKey(sliceUri)) {
+ mSliceWeakDataCache.remove(sliceUri);
+ }
+ return SliceBuilderUtils.buildSlice(getContext(), cachedSliceData);
+ } finally {
+ StrictMode.setThreadPolicy(oldPolicy);
}
- return SliceBuilderUtils.buildSlice(getContext(), cachedSliceData);
}
/**
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index 213bf00..d81734a 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -27,6 +27,7 @@
import android.app.slice.Slice;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
@@ -155,6 +156,7 @@
sliderController.setSliderPosition(newPosition);
logSliceValueChange(context, key, newPosition);
+ updateUri(context, key, isPlatformSlice);
}
/**
@@ -177,8 +179,15 @@
}
private void updateUri(Context context, String key, boolean isPlatformDefined) {
- final String path = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + key;
- final Uri uri = SliceBuilderUtils.getUri(path, isPlatformDefined);
+ final String authority = isPlatformDefined
+ ? SettingsSlicesContract.AUTHORITY
+ : SettingsSliceProvider.SLICE_AUTHORITY;
+ final Uri uri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(authority)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(key)
+ .build();
context.getContentResolver().notifyChange(uri, null /* observer */);
}
}
diff --git a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
index 7f1a0f3..4f8ed96 100644
--- a/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
+++ b/src/com/android/settings/slices/SliceDeepLinkSpringBoard.java
@@ -18,8 +18,16 @@
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
+import android.provider.Settings;
import android.util.Log;
+import com.android.settings.bluetooth.BluetoothSliceBuilder;
+import com.android.settings.location.LocationSliceBuilder;
+import com.android.settings.notification.ZenModeSliceBuilder;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.wifi.WifiSliceBuilder;
+import com.android.settings.wifi.calling.WifiCallingSliceHelper;
+
import java.net.URISyntaxException;
public class SliceDeepLinkSpringBoard extends Activity {
@@ -44,11 +52,26 @@
if (ACTION_VIEW_SLICE.equals(intent.getAction())) {
// This shouldn't matter since the slice is shown instead of the device
// index caring about the launch uri.
- Uri slice = Uri.parse(intent.getStringExtra(EXTRA_SLICE));
- SlicesDatabaseAccessor slicesDatabaseAccessor = new SlicesDatabaseAccessor(this);
- // Sadly have to block here because we don't know where to go.
- final SliceData sliceData = slicesDatabaseAccessor.getSliceDataFromUri(slice);
- Intent launchIntent = SliceBuilderUtils.getContentIntent(this, sliceData);
+ final Uri slice = Uri.parse(intent.getStringExtra(EXTRA_SLICE));
+ final Intent launchIntent;
+
+ // TODO (b/80263568) Avoid duplicating this list of Slice Uris.
+ if (WifiSliceBuilder.WIFI_URI.equals(slice)) {
+ launchIntent = WifiSliceBuilder.getIntent(this /* context */);
+ } else if (ZenModeSliceBuilder.ZEN_MODE_URI.equals(slice)) {
+ launchIntent = ZenModeSliceBuilder.getIntent(this /* context */);
+ } else if (BluetoothSliceBuilder.BLUETOOTH_URI.equals(slice)) {
+ launchIntent = BluetoothSliceBuilder.getIntent(this /* context */);
+ } else if (LocationSliceBuilder.LOCATION_URI.equals(slice)) {
+ launchIntent = LocationSliceBuilder.getIntent(this /* context */);
+ } else {
+ final SlicesDatabaseAccessor slicesDatabaseAccessor =
+ new SlicesDatabaseAccessor(this /* context */);
+ // Sadly have to block here because we don't know where to go.
+ final SliceData sliceData = slicesDatabaseAccessor.getSliceDataFromUri(slice);
+ launchIntent = SliceBuilderUtils.getContentIntent(this, sliceData);
+ }
+
startActivity(launchIntent);
} else {
startActivity(intent);
@@ -57,6 +80,10 @@
} catch (URISyntaxException e) {
Log.e(TAG, "Error decoding uri", e);
finish();
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "Couldn't launch Slice intent", e);
+ startActivity(new Intent(Settings.ACTION_SETTINGS));
+ finish();
}
}
diff --git a/src/com/android/settings/wifi/WifiSliceBuilder.java b/src/com/android/settings/wifi/WifiSliceBuilder.java
index 7df7f19..21a9455 100644
--- a/src/com/android/settings/wifi/WifiSliceBuilder.java
+++ b/src/com/android/settings/wifi/WifiSliceBuilder.java
@@ -121,6 +121,18 @@
// handle it.
}
+ public static Intent getIntent(Context context) {
+ final String screenTitle = context.getText(R.string.wifi_settings).toString();
+ final Uri contentUri = new Uri.Builder().appendPath(KEY_WIFI).build();
+ final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
+ WifiSettings.class.getName(), KEY_WIFI, screenTitle,
+ MetricsEvent.DIALOG_WIFI_AP_EDIT)
+ .setClassName(context.getPackageName(), SubSettings.class.getName())
+ .setData(contentUri);
+
+ return intent;
+ }
+
private static boolean isWifiEnabled(Context context) {
final WifiManager wifiManager = context.getSystemService(WifiManager.class);
@@ -159,14 +171,7 @@
}
private static PendingIntent getPrimaryAction(Context context) {
- final String screenTitle = context.getText(R.string.wifi_settings).toString();
- final Uri contentUri = new Uri.Builder().appendPath(KEY_WIFI).build();
- final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
- WifiSettings.class.getName(), KEY_WIFI, screenTitle,
- MetricsEvent.DIALOG_WIFI_AP_EDIT);
- intent.setClassName(context.getPackageName(), SubSettings.class.getName());
- intent.setData(contentUri);
-
+ final Intent intent = getIntent(context);
return PendingIntent.getActivity(context, 0 /* requestCode */,
intent, 0 /* flags */);
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationGesturesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationGesturesPreferenceControllerTest.java
index cd0558a..abb1cf3 100644
--- a/tests/robotests/src/com/android/settings/accessibility/MagnificationGesturesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationGesturesPreferenceControllerTest.java
@@ -114,4 +114,19 @@
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, -1))
.isEqualTo(OFF);
}
+
+ @Test
+ public void isSliceableCorrectKey_returnsTrue() {
+ final MagnificationGesturesPreferenceController controller =
+ new MagnificationGesturesPreferenceController(mContext,
+ "screen_magnification_gestures_preference_screen");
+ assertThat(controller.isSliceable()).isTrue();
+ }
+
+ @Test
+ public void isSliceableIncorrectKey_returnsFalse() {
+ final MagnificationGesturesPreferenceController controller =
+ new MagnificationGesturesPreferenceController(mContext, "bad_key");
+ assertThat(controller.isSliceable()).isFalse();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationNavbarPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationNavbarPreferenceControllerTest.java
index bca81a2..8a401d5 100644
--- a/tests/robotests/src/com/android/settings/accessibility/MagnificationNavbarPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationNavbarPreferenceControllerTest.java
@@ -158,4 +158,19 @@
sIsApplicable = applicable;
}
}
+
+ @Test
+ public void isSliceableCorrectKey_returnsTrue() {
+ final MagnificationNavbarPreferenceController controller =
+ new MagnificationNavbarPreferenceController(mContext,
+ "screen_magnification_navbar_preference_screen");
+ assertThat(controller.isSliceable()).isTrue();
+ }
+
+ @Test
+ public void isSliceableIncorrectKey_returnsFalse() {
+ final MagnificationNavbarPreferenceController controller =
+ new MagnificationNavbarPreferenceController(mContext, "bad_key");
+ assertThat(controller.isSliceable()).isFalse();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java
index 067f015..aa9efc5 100644
--- a/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/NotificationVibrationIntensityPreferenceControllerTest.java
@@ -18,10 +18,12 @@
import static android.provider.Settings.System.NOTIFICATION_VIBRATION_INTENSITY;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
+import android.content.res.Resources;
import android.os.Vibrator;
import android.provider.Settings;
import android.support.v7.preference.Preference;
@@ -48,6 +50,7 @@
private LifecycleOwner mLifecycleOwner;
private Lifecycle mLifecycle;
private Context mContext;
+ private Resources mResources;
private NotificationVibrationIntensityPreferenceController mController;
private Preference mPreference;
@@ -56,7 +59,11 @@
MockitoAnnotations.initMocks(this);
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
+ mResources = spy(mContext.getResources());
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(R.bool.config_vibration_supports_multiple_intensities))
+ .thenReturn(true);
mController = new NotificationVibrationIntensityPreferenceController(mContext) {
@Override
protected int getDefaultIntensity() {
@@ -68,7 +75,6 @@
mPreference.setSummary("Test");
when(mScreen.findPreference(mController.getPreferenceKey()))
.thenReturn(mPreference);
- mController.displayPreference(mScreen);
}
@Test
@@ -80,7 +86,10 @@
}
@Test
- public void updateState_shouldRefreshSummary() {
+ public void updateState_withMultipleIntensitySuport_shouldRefreshSummary() {
+ setSupportsMultipleIntensities(true);
+ showPreference();
+
Settings.System.putInt(mContext.getContentResolver(),
NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW);
mController.updateState(mPreference);
@@ -105,4 +114,43 @@
assertThat(mPreference.getSummary())
.isEqualTo(mContext.getString(R.string.accessibility_vibration_intensity_off));
}
+
+ @Test
+ public void updateState_withoutMultipleIntensitySupport_shouldRefreshSummary() {
+ setSupportsMultipleIntensities(false);
+ showPreference();
+
+ Settings.System.putInt(mContext.getContentResolver(),
+ NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW);
+ mController.updateState(mPreference);
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getString(R.string.switch_on_text));
+
+ Settings.System.putInt(mContext.getContentResolver(),
+ NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_HIGH);
+ mController.updateState(mPreference);
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getString(R.string.switch_on_text));
+
+ Settings.System.putInt(mContext.getContentResolver(),
+ NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_MEDIUM);
+ mController.updateState(mPreference);
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getString(R.string.switch_on_text));
+
+ Settings.System.putInt(mContext.getContentResolver(),
+ NOTIFICATION_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
+ mController.updateState(mPreference);
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getString(R.string.switch_off_text));
+ }
+
+ private void setSupportsMultipleIntensities(boolean hasSupport) {
+ when(mResources.getBoolean(R.bool.config_vibration_supports_multiple_intensities))
+ .thenReturn(hasSupport);
+ }
+
+ private void showPreference() {
+ mController.displayPreference(mScreen);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java
index 8550cf9..ecd2ff9 100644
--- a/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/VibrationPreferenceFragmentTest.java
@@ -20,16 +20,19 @@
import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_LOW;
import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_MEDIUM;
import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_OFF;
+import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_ON;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
+import android.content.res.Resources;
import android.os.UserManager;
import android.os.Vibrator;
import android.provider.Settings;
+import com.android.settings.R;
import com.android.settings.accessibility.VibrationPreferenceFragment.VibrationIntensityCandidateInfo;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -58,12 +61,11 @@
INTENSITY_TO_KEY.put(Vibrator.VIBRATION_INTENSITY_HIGH, KEY_INTENSITY_HIGH);
}
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private Activity mActivity;
@Mock
private UserManager mUserManager;
private Context mContext;
+ private Resources mResources;
private TestVibrationPreferenceFragment mFragment;
@Before
@@ -71,16 +73,18 @@
MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest();
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
+ mResources = spy(mContext.getResources());
+ when(mContext.getResources()).thenReturn(mResources);
mFragment = spy(new TestVibrationPreferenceFragment());
- doReturn(mUserManager).when(mActivity).getSystemService(Context.USER_SERVICE);
- doReturn(mContext).when(mFragment).getContext();
- mFragment.onAttach(mActivity);
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
}
@Test
public void changeIntensitySetting_shouldResultInCorrespondingKey() {
+ setSupportsMultipleIntensities(true);
+ mFragment.onAttach(mContext);
for (Map.Entry<Integer, String> entry : INTENSITY_TO_KEY.entrySet()) {
Settings.System.putInt(mContext.getContentResolver(),
Settings.System.HAPTIC_FEEDBACK_INTENSITY, entry.getKey());
@@ -89,12 +93,37 @@
}
@Test
+ public void changeIntensitySetting_WithoutMultipleIntensitySupport_shouldResultInOn() {
+ setSupportsMultipleIntensities(false);
+ mFragment.onAttach(mContext);
+ for (int intensity : INTENSITY_TO_KEY.keySet()) {
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.HAPTIC_FEEDBACK_INTENSITY, intensity);
+ final String expectedKey = intensity == Vibrator.VIBRATION_INTENSITY_OFF
+ ? KEY_INTENSITY_OFF
+ : KEY_INTENSITY_ON;
+ assertThat(mFragment.getDefaultKey()).isEqualTo(expectedKey);
+ }
+ }
+
+ @Test
public void initialDefaultKey_shouldBeMedium() {
+ setSupportsMultipleIntensities(true);
+ mFragment.onAttach(mContext);
assertThat(mFragment.getDefaultKey()).isEqualTo(KEY_INTENSITY_MEDIUM);
}
@Test
+ public void initialDefaultKey_WithoutMultipleIntensitySupport_shouldBeOn() {
+ setSupportsMultipleIntensities(false);
+ mFragment.onAttach(mContext);
+ assertThat(mFragment.getDefaultKey()).isEqualTo(KEY_INTENSITY_ON);
+ }
+
+ @Test
public void candidates_shouldBeSortedByIntensity() {
+ setSupportsMultipleIntensities(true);
+ mFragment.onAttach(mContext);
final List<? extends CandidateInfo> candidates = mFragment.getCandidates();
assertThat(candidates.size()).isEqualTo(INTENSITY_TO_KEY.size());
VibrationIntensityCandidateInfo prevCandidate =
@@ -106,6 +135,11 @@
}
}
+ private void setSupportsMultipleIntensities(boolean hasSupport) {
+ when(mResources.getBoolean(R.bool.config_vibration_supports_multiple_intensities))
+ .thenReturn(hasSupport);
+ }
+
private class TestVibrationPreferenceFragment extends VibrationPreferenceFragment {
@Override
protected int getPreferenceScreenResId() {
@@ -129,5 +163,10 @@
protected int getDefaultVibrationIntensity() {
return Vibrator.VIBRATION_INTENSITY_MEDIUM;
}
+
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/SmartBatteryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/SmartBatteryPreferenceControllerTest.java
index 717ba83..b1e9f51 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/SmartBatteryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/SmartBatteryPreferenceControllerTest.java
@@ -115,4 +115,11 @@
return Settings.Global.getInt(mContentResolver,
Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, ON);
}
+
+ @Test
+ public void isSliceableCorrectKey_returnsTrue() {
+ final SmartBatteryPreferenceController controller =
+ new SmartBatteryPreferenceController(mContext);
+ assertThat(controller.isSliceable()).isTrue();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/notification/AlarmVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/AlarmVolumePreferenceControllerTest.java
index 6e8476c..4f48b77 100644
--- a/tests/robotests/src/com/android/settings/notification/AlarmVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/AlarmVolumePreferenceControllerTest.java
@@ -73,4 +73,9 @@
public void getAudioStream_shouldReturnAlarm() {
assertThat(mController.getAudioStream()).isEqualTo(AudioManager.STREAM_ALARM);
}
+
+ @Test
+ public void isSliceableCorrectKey_returnsTrue() {
+ assertThat(mController.isSliceable()).isTrue();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/search/DeviceIndexUpdateJobServiceTest.java b/tests/robotests/src/com/android/settings/search/DeviceIndexUpdateJobServiceTest.java
index b5de973..1c02b99 100644
--- a/tests/robotests/src/com/android/settings/search/DeviceIndexUpdateJobServiceTest.java
+++ b/tests/robotests/src/com/android/settings/search/DeviceIndexUpdateJobServiceTest.java
@@ -45,7 +45,7 @@
import java.util.List;
import androidx.slice.Slice;
-import androidx.slice.SliceManager;
+import androidx.slice.SliceViewManager;
import androidx.slice.SliceMetadata;
@RunWith(SettingsRobolectricTestRunner.class)
@@ -57,17 +57,17 @@
private Activity mActivity;
private DeviceIndexUpdateJobService mJob;
- private SliceManager mSliceManager;
+ private SliceViewManager mSliceManager;
@Before
public void setup() {
FakeFeatureFactory.setupForTest();
mActivity = spy(Robolectric.buildActivity(Activity.class).create().visible().get());
mJob = spy(new DeviceIndexUpdateJobService());
- mSliceManager = mock(SliceManager.class);
+ mSliceManager = mock(SliceViewManager.class);
doReturn(mActivity.getPackageName()).when(mJob).getPackageName();
- doReturn(mSliceManager).when(mJob).getSliceManager();
+ doReturn(mSliceManager).when(mJob).getSliceViewManager();
doNothing().when(mJob).jobFinished(null, false);
}
@@ -144,4 +144,4 @@
when(mSliceManager.getSliceDescendants(BASE_URI)).thenReturn(mUris);
}
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index df960d8..21bef61 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -18,9 +18,7 @@
package com.android.settings.slices;
import static android.content.ContentResolver.SCHEME_CONTENT;
-
import static com.google.common.truth.Truth.assertThat;
-
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -38,19 +36,24 @@
import android.provider.SettingsSlicesContract;
import android.util.ArraySet;
-import com.android.settings.location.LocationSliceBuilder;
-import com.android.settings.wifi.WifiSliceBuilder;
import com.android.settings.bluetooth.BluetoothSliceBuilder;
+import com.android.settings.location.LocationSliceBuilder;
import com.android.settings.notification.ZenModeSliceBuilder;
import com.android.settings.testutils.DatabaseTestUtils;
import com.android.settings.testutils.FakeToggleController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowThreadUtils;
+import com.android.settings.wifi.WifiSliceBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
import java.util.Arrays;
import java.util.Collection;
@@ -66,6 +69,7 @@
* TODO Investigate using ShadowContentResolver.registerProviderInternal(String, ContentProvider)
*/
@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = ShadowThreadUtils.class)
public class SettingsSliceProviderTest {
private static final String KEY = "KEY";
@@ -98,6 +102,7 @@
public void setUp() {
mContext = spy(RuntimeEnvironment.application);
mProvider = spy(new SettingsSliceProvider());
+ ShadowStrictMode.reset();
mProvider.mSliceWeakDataCache = new HashMap<>();
mProvider.mSliceDataCache = new HashMap<>();
mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
@@ -112,6 +117,7 @@
@After
public void cleanUp() {
+ ShadowThreadUtils.reset();
DatabaseTestUtils.clearDb(mContext);
}
@@ -184,7 +190,8 @@
}
@Test
- public void onBindSlice_shouldNotOverrideStrictMode() {
+ public void onBindSlice_mainThread_shouldNotOverrideStrictMode() {
+ ShadowThreadUtils.setIsMainThread(true);
final StrictMode.ThreadPolicy oldThreadPolicy = StrictMode.getThreadPolicy();
SliceData data = getDummyData();
mProvider.mSliceWeakDataCache.put(data.getUri(), data);
@@ -196,6 +203,18 @@
}
@Test
+ @Config(shadows = ShadowStrictMode.class)
+ public void onBindSlice_backgroundThread_shouldOverrideStrictMode() {
+ ShadowThreadUtils.setIsMainThread(false);
+
+ SliceData data = getDummyData();
+ mProvider.mSliceWeakDataCache.put(data.getUri(), data);
+ mProvider.onBindSlice(data.getUri());
+
+ assertThat(ShadowStrictMode.isThreadPolicyOverridden()).isTrue();
+ }
+
+ @Test
public void onBindSlice_requestsBlockedSlice_retunsNull() {
final String blockedKey = "blocked_key";
final Set<String> blockedSet = new ArraySet<>();
@@ -456,7 +475,7 @@
mDb.replaceOrThrow(SlicesDatabaseHelper.Tables.TABLE_SLICES_INDEX, null, values);
}
- private SliceData getDummyData() {
+ private static SliceData getDummyData() {
return new SliceData.Builder()
.setKey(KEY)
.setTitle(TITLE)
@@ -468,4 +487,24 @@
.setPreferenceControllerClassName(PREF_CONTROLLER)
.build();
}
+
+ @Implements(value = StrictMode.class, inheritImplementationMethods = true)
+ public static class ShadowStrictMode {
+
+ private static int sSetThreadPolicyCount;
+
+ @Resetter
+ public static void reset() {
+ sSetThreadPolicyCount = 0;
+ }
+
+ @Implementation
+ public static void setThreadPolicy(final StrictMode.ThreadPolicy policy) {
+ sSetThreadPolicyCount++;
+ }
+
+ public static boolean isThreadPolicyOverridden() {
+ return sSetThreadPolicyCount != 0;
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
index 5f0bc96..25f0d0c 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
@@ -96,8 +96,16 @@
@Test
public void onReceive_toggleChanged() {
final String key = "key";
+ final Uri uri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(key)
+ .build();
mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
insertSpecialCase(key);
+ final ContentResolver resolver = mock(ContentResolver.class);
+ doReturn(resolver).when(mContext).getContentResolver();
// Turn on toggle setting
FakeToggleController fakeToggleController = new FakeToggleController(mContext, key);
fakeToggleController.setChecked(true);
@@ -121,6 +129,7 @@
assertThat(namePair.first).isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME);
assertThat(namePair.second).isEqualTo(fakeToggleController.getPreferenceKey());
+ verify(resolver).notifyChange(uri, null);
assertThat(valuePair.first)
.isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE);
assertThat(valuePair.second).isEqualTo(0);
@@ -183,6 +192,14 @@
@Test
public void onReceive_sliderChanged() {
final String key = "key";
+ final Uri uri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(key)
+ .build();
+ final ContentResolver resolver = mock(ContentResolver.class);
+ doReturn(resolver).when(mContext).getContentResolver();
final int position = FakeSliderController.MAX_STEPS - 1;
final int oldPosition = FakeSliderController.MAX_STEPS;
mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
@@ -213,6 +230,7 @@
assertThat(namePair.first).isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME);
assertThat(namePair.second).isEqualTo(key);
+ verify(resolver).notifyChange(uri, null);
assertThat(valuePair.first)
.isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE);
assertThat(valuePair.second).isEqualTo(position);
@@ -286,8 +304,12 @@
// Check the value is the same and the Uri has been notified.
assertThat(fakeToggleController.isChecked()).isTrue();
- final Uri expectedUri = SliceBuilderUtils.getUri(
- SettingsSlicesContract.PATH_SETTING_ACTION + "/" + key, false);
+ final Uri expectedUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(key)
+ .build();
verify(resolver).notifyChange(eq(expectedUri), eq(null));
}
@@ -323,8 +345,12 @@
// Check position is the same and the Uri has been notified.
assertThat(fakeSliderController.getSliderPosition()).isEqualTo(oldPosition);
- final Uri expectedUri = SliceBuilderUtils.getUri(
- SettingsSlicesContract.PATH_SETTING_ACTION + "/" + key, false);
+ final Uri expectedUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(key)
+ .build();
verify(resolver).notifyChange(eq(expectedUri), eq(null));
}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowThreadUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowThreadUtils.java
index 6b0411e..9513098 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowThreadUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowThreadUtils.java
@@ -20,10 +20,18 @@
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
@Implements(ThreadUtils.class)
public class ShadowThreadUtils {
+ private static boolean sIsMainThread = true;
+
+ @Resetter
+ public static void reset() {
+ sIsMainThread = true;
+ }
+
@Implementation
public static void postOnBackgroundThread(Runnable runnable) {
runnable.run();
@@ -33,4 +41,14 @@
public static void postOnMainThread(Runnable runnable) {
runnable.run();
}
+
+ @Implementation
+ public static boolean isMainThread() {
+ return sIsMainThread;
+ }
+
+ public static void setIsMainThread(boolean isMainThread) {
+ sIsMainThread = isMainThread;
+ }
+
}
diff --git a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
index e7c5d6e..91057b8 100644
--- a/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
+++ b/tests/unit/src/com/android/settings/slices/SliceDeepLinkSpringBoardTest.java
@@ -21,14 +21,22 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
+import com.android.settings.bluetooth.BluetoothSliceBuilder;
+import com.android.settings.location.LocationSliceBuilder;
+import com.android.settings.notification.ZenModeSliceBuilder;
+import com.android.settings.wifi.WifiSliceBuilder;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
+@MediumTest
public class SliceDeepLinkSpringBoardTest {
private Context mContext;
@@ -38,18 +46,57 @@
}
@Test
- public void launcheDeepLinkIntent_shouldNotCrash() {
- final Uri springBoardIntentUri = createDeepLink(
- new Intent(SliceDeepLinkSpringBoard.ACTION_VIEW_SLICE)
- .setPackage(mContext.getPackageName())
- .putExtra(SliceDeepLinkSpringBoard.EXTRA_SLICE,
- "content://com.android.settings.slices/action/test_slice")
- .toUri(Intent.URI_ANDROID_APP_SCHEME));
-
- final Intent deepLinkIntent = new Intent(Intent.ACTION_VIEW)
- .setData(springBoardIntentUri)
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ @Presubmit
+ public void launchesDeepLinkIntent_shouldNotCrash() {
+ final Intent deepLinkIntent = getSpringboardIntent(
+ "content://com.android.settings.slices/action/test_slice");
mContext.startActivity(deepLinkIntent);
}
+
+ @Test
+ @Presubmit
+ public void launchesDeepLinkIntent_wifiSlice_shouldNotCrash() {
+ final Intent deepLinkIntent = getSpringboardIntent(WifiSliceBuilder.WIFI_URI.toString());
+
+ mContext.startActivity(deepLinkIntent);
+ }
+
+ @Test
+ @Presubmit
+ public void launchesDeepLinkIntent_bluetoothSlice_shouldNotCrash() {
+ final Intent deepLinkIntent = getSpringboardIntent(
+ BluetoothSliceBuilder.BLUETOOTH_URI.toString());
+
+ mContext.startActivity(deepLinkIntent);
+ }
+
+ @Test
+ @Presubmit
+ public void launchesDeepLinkIntent_dndSlice_shouldNotCrash() {
+ final Intent deepLinkIntent = getSpringboardIntent(
+ ZenModeSliceBuilder.ZEN_MODE_URI.toString());
+
+ mContext.startActivity(deepLinkIntent);
+ }
+
+ @Test
+ @Presubmit
+ public void launchesDeepLinkIntent_locationSlice_shouldNotCrash() {
+ final Intent deepLinkIntent = getSpringboardIntent(
+ LocationSliceBuilder.LOCATION_URI.toString());
+
+ mContext.startActivity(deepLinkIntent);
+ }
+
+ private Intent getSpringboardIntent(String uriString) {
+ final Uri uri = createDeepLink(new Intent(SliceDeepLinkSpringBoard.ACTION_VIEW_SLICE)
+ .setPackage(mContext.getPackageName())
+ .putExtra(SliceDeepLinkSpringBoard.EXTRA_SLICE, uriString)
+ .toUri(Intent.URI_ANDROID_APP_SCHEME));
+
+ return new Intent(Intent.ACTION_VIEW)
+ .setData(uri)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
}