Merge "Unavailable Slices includes DISABLED_DEPENDENT settings" into pi-dev
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index c54d138..05f0974 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -17,6 +17,8 @@
package com.android.settings.slices;
import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED;
@@ -47,7 +49,9 @@
import com.android.settingslib.core.AbstractPreferenceController;
import android.support.v4.graphics.drawable.IconCompat;
+
import androidx.slice.Slice;
+import androidx.slice.SliceMetadata;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.SliceAction;
@@ -75,7 +79,8 @@
// action name).
FeatureFactory.getFactory(context).getMetricsFeatureProvider()
.action(context, MetricsEvent.ACTION_SETTINGS_SLICE_REQUESTED, sliceNamePair);
- if (!controller.isAvailable()) {
+
+ if (controller.getAvailabilityStatus() != AVAILABLE) {
return buildUnavailableSlice(context, sliceData, controller);
}
@@ -145,6 +150,60 @@
sliceData.getKey());
}
+ /**
+ * @return {@link PendingIntent} for a non-primary {@link SliceAction}.
+ */
+ public static PendingIntent getActionIntent(Context context, String action, SliceData data) {
+ Intent intent = new Intent(action);
+ intent.setClass(context, SliceBroadcastReceiver.class);
+ intent.putExtra(EXTRA_SLICE_KEY, data.getKey());
+ intent.putExtra(EXTRA_SLICE_PLATFORM_DEFINED, data.isPlatformDefined());
+ return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ }
+
+ /**
+ * @return {@link PendingIntent} for the primary {@link SliceAction}.
+ */
+ public static PendingIntent getContentIntent(Context context, SliceData sliceData) {
+ Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
+ sliceData.getFragmentClassName(), sliceData.getKey(), sliceData.getScreenTitle(),
+ 0 /* TODO */);
+ intent.setClassName("com.android.settings", SubSettings.class.getName());
+ return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */);
+ }
+
+ /**
+ * @return {@link PendingIntent} to the Settings home page.
+ */
+ public static PendingIntent getSettingsIntent(Context context) {
+ final PackageManager manager = context.getPackageManager();
+ final Intent intent = manager.getLaunchIntentForPackage(context.getPackageName());
+ return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */);
+ }
+
+ /**
+ * @return the summary text for a {@link Slice} built for {@param sliceData}.
+ */
+ public static CharSequence getSubtitleText(Context context,
+ AbstractPreferenceController controller, SliceData sliceData) {
+ CharSequence summaryText;
+ if (controller != null) {
+ summaryText = controller.getSummary();
+
+ if (isValidSummary(context, summaryText)) {
+ return summaryText;
+ }
+ }
+
+ summaryText = sliceData.getSummary();
+ if (isValidSummary(context, summaryText)) {
+ return summaryText;
+ }
+
+ return "";
+ }
+
public static Uri getUri(String path, boolean isPlatformSlice) {
final String authority = isPlatformSlice
? SettingsSlicesContract.AUTHORITY
@@ -227,49 +286,6 @@
return getActionIntent(context, SettingsSliceProvider.ACTION_SLIDER_CHANGED, sliceData);
}
- private static PendingIntent getActionIntent(Context context, String action, SliceData data) {
- Intent intent = new Intent(action);
- intent.setClass(context, SliceBroadcastReceiver.class);
- intent.putExtra(EXTRA_SLICE_KEY, data.getKey());
- intent.putExtra(EXTRA_SLICE_PLATFORM_DEFINED, data.isPlatformDefined());
- return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
- }
-
- private static PendingIntent getContentIntent(Context context, SliceData sliceData) {
- Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
- sliceData.getFragmentClassName(), sliceData.getKey(), sliceData.getScreenTitle(),
- 0 /* TODO */);
- intent.setClassName("com.android.settings", SubSettings.class.getName());
- return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */);
- }
-
- private static PendingIntent getSettingsIntent(Context context) {
- final PackageManager manager = context.getPackageManager();
- final Intent intent = manager.getLaunchIntentForPackage(context.getPackageName());
- return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */);
- }
-
- @VisibleForTesting
- static CharSequence getSubtitleText(Context context, AbstractPreferenceController controller,
- SliceData sliceData) {
- CharSequence summaryText;
- if (controller != null) {
- summaryText = controller.getSummary();
-
- if (isValidSummary(context, summaryText)) {
- return summaryText;
- }
- }
-
- summaryText = sliceData.getSummary();
- if (isValidSummary(context, summaryText)) {
- return summaryText;
- }
-
- return "";
- }
-
private static boolean isValidSummary(Context context, CharSequence summary) {
if (summary == null || TextUtils.isEmpty(summary.toString().trim())) {
return false;
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 1f3f40f..58ee969 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -17,6 +17,8 @@
package com.android.settings.slices;
import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -24,6 +26,7 @@
import android.content.ContentResolver;
import android.content.Context;
+import android.content.res.Resources;
import android.net.Uri;
import android.provider.Settings;
import android.provider.SettingsSlicesContract;
@@ -36,6 +39,7 @@
import com.android.settings.testutils.FakeSliderController;
import com.android.settings.testutils.FakeToggleController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.SliceTester;
import org.junit.Before;
import org.junit.Test;
@@ -44,6 +48,8 @@
import org.robolectric.RuntimeEnvironment;
import androidx.slice.Slice;
+import androidx.slice.SliceProvider;
+import androidx.slice.widget.SliceLiveData;
@RunWith(SettingsRobolectricTestRunner.class)
public class SliceBuilderUtilsTest {
@@ -55,8 +61,9 @@
private final String FRAGMENT_NAME = "fragment name";
private final int ICON = 1234; // I declare a thumb war
private final Uri URI = Uri.parse("content://com.android.settings.slices/test");
- private final Class PREF_CONTROLLER = FakeToggleController.class;
- private final Class PREF_CONTROLLER2 = FakeContextOnlyPreferenceController.class;
+ private final Class TOGGLE_CONTROLLER = FakeToggleController.class;
+ private final Class SLIDER_CONTROLLER = FakeSliderController.class;
+ private final Class CONTEXT_CONTROLLER = FakeContextOnlyPreferenceController.class;
private final String INTENT_PATH = SettingsSlicesContract.PATH_SETTING_INTENT + "/" + KEY;
private final String ACTION_PATH = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + KEY;
@@ -67,23 +74,50 @@
@Before
public void setUp() {
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
mFeatureFactory = FakeFeatureFactory.setupForTest();
mLoggingArgumentCatpor = ArgumentCaptor.forClass(Pair.class);
+
+ // Prevent crash in SliceMetadata.
+ Resources resources = spy(mContext.getResources());
+ doReturn(60).when(resources).getDimensionPixelSize(anyInt());
+ doReturn(resources).when(mContext).getResources();
+
+ // Set-up specs for SliceMetadata.
+ SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
}
@Test
- public void testBuildSlice_returnsMatchingSlice() {
- Slice slice = SliceBuilderUtils.buildSlice(mContext, getDummyData());
+ public void buildIntentSlice_returnsMatchingSlice() {
+ final SliceData sliceData = getDummyData(CONTEXT_CONTROLLER, SliceData.SliceType.INTENT);
+ final Slice slice = SliceBuilderUtils.buildSlice(mContext, sliceData);
- assertThat(slice).isNotNull(); // TODO improve test for Slice content
+ SliceTester.testSettingsIntentSlice(mContext, slice, sliceData);
}
@Test
- public void testSliderSlice_returnsSeekBarSlice() {
- final SliceData data = getDummyData(FakeSliderController.class);
+ public void buildToggleSlice_returnsMatchingSlice() {
+ final SliceData dummyData = getDummyData(TOGGLE_CONTROLLER, SliceData.SliceType.SWITCH);
+
+ final Slice slice = SliceBuilderUtils.buildSlice(mContext, dummyData);
+ verify(mFeatureFactory.metricsFeatureProvider)
+ .action(eq(mContext), eq(MetricsEvent.ACTION_SETTINGS_SLICE_REQUESTED),
+ mLoggingArgumentCatpor.capture());
+ final Pair<Integer, Object> capturedLoggingPair = mLoggingArgumentCatpor.getValue();
+
+ assertThat(capturedLoggingPair.first)
+ .isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME);
+ assertThat(capturedLoggingPair.second)
+ .isEqualTo(dummyData.getKey());
+ SliceTester.testSettingsToggleSlice(mContext, slice, dummyData);
+ }
+
+ @Test
+ public void buildSliderSlice_returnsMatchingSlice() {
+ final SliceData data = getDummyData(SLIDER_CONTROLLER, SliceData.SliceType.SLIDER);
+
+
final Slice slice = SliceBuilderUtils.buildSlice(mContext, data);
-
verify(mFeatureFactory.metricsFeatureProvider)
.action(eq(mContext), eq(MetricsEvent.ACTION_SETTINGS_SLICE_REQUESTED),
mLoggingArgumentCatpor.capture());
@@ -93,7 +127,7 @@
.isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME);
assertThat(capturedLoggingPair.second)
.isEqualTo(data.getKey());
- assertThat(slice).isNotNull();
+ SliceTester.testSettingsSliderSlice(mContext, slice, data);
}
@Test
@@ -159,7 +193,8 @@
@Test
public void testGetPreferenceController_contextOnly_buildsMatchingController() {
final BasePreferenceController controller =
- SliceBuilderUtils.getPreferenceController(mContext, getDummyData(PREF_CONTROLLER2));
+ SliceBuilderUtils.getPreferenceController(mContext,
+ getDummyData(CONTEXT_CONTROLLER, 0));
assertThat(controller).isInstanceOf(FakeContextOnlyPreferenceController.class);
}
@@ -176,7 +211,7 @@
@Test
public void testDynamicSummary_returnsFragmentSummary() {
- final SliceData data = getDummyData((String) null);
+ final SliceData data = getDummyData(null);
final FakePreferenceController controller = spy(
new FakePreferenceController(mContext, KEY));
final String controllerSummary = "new_Summary";
@@ -189,7 +224,7 @@
@Test
public void testDynamicSummary_returnsSliceEmptyString() {
- final SliceData data = getDummyData((String) null);
+ final SliceData data = getDummyData(null);
final FakePreferenceController controller = new FakePreferenceController(mContext, KEY);
final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data);
@@ -285,31 +320,34 @@
@Test
public void testUnsupportedSlice_validTitleSummary() {
- final SliceData data = getDummyData(FakeUnavailablePreferenceController.class.getName());
+ final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
+ SliceData.SliceType.SWITCH);
Settings.System.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.DISABLED_UNSUPPORTED);
final Slice slice = SliceBuilderUtils.buildSlice(mContext, data);
- assertThat(slice).isNotNull();
+ SliceTester.testSettingsUnavailableSlice(mContext, slice, data);
}
@Test
public void testDisabledForUserSlice_validTitleSummary() {
- final SliceData data = getDummyData(FakeUnavailablePreferenceController.class.getName());
+ final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
+ SliceData.SliceType.SWITCH);
Settings.System.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.DISABLED_FOR_USER);
final Slice slice = SliceBuilderUtils.buildSlice(mContext, data);
- assertThat(slice).isNotNull();
+ SliceTester.testSettingsUnavailableSlice(mContext, slice, data);
}
@Test
- public void testDisabledDependententSettingSlice_validTitleSummary() {
- final SliceData data = getDummyData(FakeUnavailablePreferenceController.class.getName());
+ public void testDisabledDependentSettingSlice_validTitleSummary() {
+ final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
+ SliceData.SliceType.INTENT);
Settings.System.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
@@ -325,12 +363,13 @@
.isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME);
assertThat(capturedLoggingPair.second)
.isEqualTo(data.getKey());
- assertThat(slice).isNotNull();
+ SliceTester.testSettingsUnavailableSlice(mContext, slice, data);
}
@Test
public void testUnavailableUnknownSlice_validTitleSummary() {
- final SliceData data = getDummyData(FakeUnavailablePreferenceController.class.getName());
+ final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
+ SliceData.SliceType.SWITCH);
Settings.System.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.UNAVAILABLE_UNKNOWN);
@@ -347,22 +386,22 @@
.isEqualTo(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME);
assertThat(capturedLoggingPair.second)
.isEqualTo(data.getKey());
- assertThat(slice).isNotNull();
+ SliceTester.testSettingsUnavailableSlice(mContext, slice, data);
}
private SliceData getDummyData() {
- return getDummyData(PREF_CONTROLLER, SUMMARY);
+ return getDummyData(TOGGLE_CONTROLLER, SUMMARY, SliceData.SliceType.SWITCH);
}
private SliceData getDummyData(String summary) {
- return getDummyData(PREF_CONTROLLER, summary);
+ return getDummyData(TOGGLE_CONTROLLER, summary, SliceData.SliceType.SWITCH);
}
- private SliceData getDummyData(Class prefController) {
- return getDummyData(prefController, SUMMARY);
+ private SliceData getDummyData(Class prefController, int sliceType) {
+ return getDummyData(prefController, SUMMARY, sliceType);
}
- private SliceData getDummyData(Class prefController, String summary) {
+ private SliceData getDummyData(Class prefController, String summary, int sliceType) {
return new SliceData.Builder()
.setKey(KEY)
.setTitle(TITLE)
@@ -372,6 +411,7 @@
.setFragmentName(FRAGMENT_NAME)
.setUri(URI)
.setPreferenceControllerClassName(prefController.getName())
+ .setSliceType(sliceType)
.build();
}
}
diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
new file mode 100644
index 0000000..ef62d77
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
@@ -0,0 +1,170 @@
+/*
+ * 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;
+
+import static android.app.slice.Slice.HINT_TITLE;
+import static android.app.slice.SliceItem.FORMAT_TEXT;
+
+import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
+import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
+import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED;
+import static com.android.settings.core.BasePreferenceController.UNAVAILABLE_UNKNOWN;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.PendingIntent;
+import android.content.Context;
+
+import java.util.List;
+
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
+import androidx.slice.core.SliceAction;
+import androidx.slice.core.SliceQuery;
+
+import android.support.v4.graphics.drawable.IconCompat;
+
+import com.android.settings.slices.SettingsSliceProvider;
+import com.android.settings.slices.SliceBuilderUtils;
+import com.android.settings.slices.SliceData;
+
+/**
+ * Testing utility class to verify the contents of the different Settings Slices.
+ *
+ * TODO (77712944) check Summary, range (metadata.getRange()), toggle icons.
+ */
+public class SliceTester {
+
+ /**
+ * Test the contents of an intent based slice, including:
+ * - No toggles
+ * - Correct intent
+ * - Correct title
+ */
+ public static void testSettingsIntentSlice(Context context, Slice slice, SliceData sliceData) {
+ final SliceMetadata metadata = SliceMetadata.from(context, slice);
+
+ final List<SliceAction> toggles = metadata.getToggles();
+ assertThat(toggles).isEmpty();
+
+ final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction();
+ assertThat(primaryPendingIntent).isEqualTo(
+ SliceBuilderUtils.getContentIntent(context, sliceData));
+
+ final List<SliceItem> sliceItems = slice.getItems();
+ assertTitle(sliceItems, sliceData.getTitle());
+ }
+
+ /**
+ * Test the contents of an toggle based slice, including:
+ * - Contains one toggle
+ * - Correct toggle intent
+ * - Correct content intent
+ * - Correct title
+ */
+ public static void testSettingsToggleSlice(Context context, Slice slice, SliceData sliceData) {
+ final SliceMetadata metadata = SliceMetadata.from(context, slice);
+
+ final List<SliceAction> toggles = metadata.getToggles();
+ assertThat(toggles).hasSize(1);
+
+ final SliceAction mainToggleAction = toggles.get(0);
+
+ final IconCompat expectedToggleIcon = IconCompat.createWithResource(context,
+ sliceData.getIconResource());
+ assertThat(mainToggleAction.getIcon()).isNull();
+
+ // Check intent in Toggle Action
+ final PendingIntent togglePendingIntent = mainToggleAction.getAction();
+ assertThat(togglePendingIntent).isEqualTo(SliceBuilderUtils.getActionIntent(context,
+ SettingsSliceProvider.ACTION_TOGGLE_CHANGED, sliceData));
+
+ // Check primary intent
+ final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction();
+ assertThat(primaryPendingIntent).isEqualTo(
+ SliceBuilderUtils.getContentIntent(context, sliceData));
+
+ final List<SliceItem> sliceItems = slice.getItems();
+ assertTitle(sliceItems, sliceData.getTitle());
+ }
+
+ /**
+ * Test the contents of an slider based slice, including:
+ * - No intent
+ * - Correct title
+ */
+ public static void testSettingsSliderSlice(Context context, Slice slice, SliceData sliceData) {
+ final SliceMetadata metadata = SliceMetadata.from(context, slice);
+
+ final IconCompat expectedToggleIcon = IconCompat.createWithResource(context,
+ sliceData.getIconResource());
+
+ // Check primary intent
+ final SliceAction primaryAction = metadata.getPrimaryAction();
+ assertThat(primaryAction).isNull();
+
+ final List<SliceItem> sliceItems = slice.getItems();
+ assertTitle(sliceItems, sliceData.getTitle());
+ }
+
+ /**
+ * Test the contents of an unavailable slice, including:
+ * - No toggles
+ * - Correct title
+ * - Correct intent
+ */
+ public static void testSettingsUnavailableSlice(Context context, Slice slice,
+ SliceData sliceData) {
+ final SliceMetadata metadata = SliceMetadata.from(context, slice);
+
+ final List<SliceAction> toggles = metadata.getToggles();
+ assertThat(toggles).isEmpty();
+
+ final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction();
+ final int availabilityStatus = SliceBuilderUtils.getPreferenceController(context,
+ sliceData).getAvailabilityStatus();
+ switch (availabilityStatus) {
+ case DISABLED_UNSUPPORTED:
+ case UNAVAILABLE_UNKNOWN:
+ assertThat(primaryPendingIntent).isEqualTo(
+ SliceBuilderUtils.getSettingsIntent(context));
+ break;
+ case DISABLED_FOR_USER:
+ case DISABLED_DEPENDENT_SETTING:
+ assertThat(primaryPendingIntent).isEqualTo(
+ SliceBuilderUtils.getContentIntent(context, sliceData));
+ break;
+ }
+
+ final List<SliceItem> sliceItems = slice.getItems();
+ assertTitle(sliceItems, sliceData.getTitle());
+ }
+
+ private static void assertTitle(List<SliceItem> sliceItems, String title) {
+ boolean hasTitle = false;
+ for (SliceItem item : sliceItems) {
+ List<SliceItem> titles = SliceQuery.findAll(item, FORMAT_TEXT, HINT_TITLE,
+ null /* non-hints */);
+ if (titles != null & titles.size() == 1) {
+ assertThat(titles.get(0).getText()).isEqualTo(title);
+ hasTitle = true;
+ }
+ }
+ assertThat(hasTitle).isTrue();
+ }
+}
\ No newline at end of file