diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java index 970b72a9caf..a68ed19db1d 100644 --- a/src/com/android/settings/slices/SliceBroadcastReceiver.java +++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java @@ -71,7 +71,7 @@ public class SliceBroadcastReceiver extends BroadcastReceiver { throw new IllegalStateException("No key passed to Intent for toggle controller"); } - BasePreferenceController controller = getBasePreferenceController(context, key); + final BasePreferenceController controller = getPreferenceController(context, key); if (!(controller instanceof TogglePreferenceController)) { throw new IllegalStateException("Toggle action passed for a non-toggle key: " + key); @@ -79,12 +79,12 @@ public class SliceBroadcastReceiver extends BroadcastReceiver { // TODO post context.getContentResolver().notifyChanged(uri, null) in the Toggle controller // so that it's automatically broadcast to any slice. - TogglePreferenceController toggleController = (TogglePreferenceController) controller; - boolean currentValue = toggleController.isChecked(); + final TogglePreferenceController toggleController = (TogglePreferenceController) controller; + final boolean currentValue = toggleController.isChecked(); toggleController.setChecked(!currentValue); } - private BasePreferenceController getBasePreferenceController(Context context, String key) { + private BasePreferenceController getPreferenceController(Context context, String key) { final SlicesDatabaseAccessor accessor = new SlicesDatabaseAccessor(context); final SliceData sliceData = accessor.getSliceDataFromKey(key); return SliceBuilderUtils.getPreferenceController(context, sliceData); diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java index 014ead28c22..e9152bab74a 100644 --- a/src/com/android/settings/slices/SliceBuilderUtils.java +++ b/src/com/android/settings/slices/SliceBuilderUtils.java @@ -24,10 +24,13 @@ import android.content.Intent; import android.graphics.drawable.Icon; import android.text.TextUtils; +import com.android.internal.annotations.VisibleForTesting; +import com.android.settings.R; import com.android.settings.SubSettings; import com.android.settings.core.BasePreferenceController; import com.android.settings.core.TogglePreferenceController; import com.android.settings.search.DatabaseIndexingUtils; +import com.android.settingslib.core.AbstractPreferenceController; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -54,21 +57,17 @@ public class SliceBuilderUtils { public static Slice buildSlice(Context context, SliceData sliceData) { final PendingIntent contentIntent = getContentIntent(context, sliceData); final Icon icon = Icon.createWithResource(context, sliceData.getIconResource()); - String summaryText = sliceData.getSummary(); - String subtitleText = TextUtils.isEmpty(summaryText) - ? sliceData.getScreenTitle() - : summaryText; + final BasePreferenceController controller = getPreferenceController(context, sliceData); - RowBuilder builder = new RowBuilder(context, sliceData.getUri()) + final String subtitleText = getSubtitleText(context, controller, sliceData); + + final RowBuilder builder = new RowBuilder(context, sliceData.getUri()) .setTitle(sliceData.getTitle()) .setTitleItem(icon) .setSubtitle(subtitleText) .setContentIntent(contentIntent); - BasePreferenceController controller = getPreferenceController(context, sliceData); - // TODO (b/71640747) Respect setting availability. - // TODO (b/71640678) Add dynamic summary text. if (controller instanceof TogglePreferenceController) { addToggleAction(context, builder, ((TogglePreferenceController) controller).isChecked(), @@ -82,7 +81,7 @@ public class SliceBuilderUtils { /** * Looks at the {@link SliceData#preferenceController} from {@param sliceData} and attempts to - * build a {@link BasePreferenceController}. + * build an {@link AbstractPreferenceController}. */ public static BasePreferenceController getPreferenceController(Context context, SliceData sliceData) { @@ -122,4 +121,35 @@ public class SliceBuilderUtils { intent.setClassName("com.android.settings", SubSettings.class.getName()); return PendingIntent.getActivity(context, 0 /* requestCode */, intent, 0 /* flags */); } + + @VisibleForTesting + static String getSubtitleText(Context context, AbstractPreferenceController controller, + SliceData sliceData) { + String summaryText = sliceData.getSummary(); + if (isValidSummary(context, summaryText)) { + return summaryText; + } + + if (controller != null) { + summaryText = controller.getSummary(); + + if (isValidSummary(context, summaryText)) { + return summaryText; + } + } + + return sliceData.getScreenTitle(); + } + + private static boolean isValidSummary(Context context, String summary) { + if (summary == null || TextUtils.isEmpty(summary.trim())) { + return false; + } + + final String placeHolder = context.getString(R.string.summary_placeholder); + final String doublePlaceHolder = context.getString(R.string.summary_two_lines_placeholder); + + return !(TextUtils.equals(summary, placeHolder) + || TextUtils.equals(summary, doublePlaceHolder)); + } } diff --git a/src/com/android/settings/slices/SliceDataConverter.java b/src/com/android/settings/slices/SliceDataConverter.java index 4d9b7a5ed6c..c10753f5a73 100644 --- a/src/com/android/settings/slices/SliceDataConverter.java +++ b/src/com/android/settings/slices/SliceDataConverter.java @@ -163,7 +163,7 @@ class SliceDataConverter { // TODO (b/67996923) Non-controller Slices should become intent-only slices. // Note that without a controller, dynamic summaries are impossible. - // TODO (b/67996923) This will not work if preferences have nested intens: + // TODO (b/67996923) This will not work if preferences have nested intents: // // controllerClassName = XmlParserUtils.getController(mContext, attrs); diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java similarity index 51% rename from tests/robotests/src/com/android/settings/slices/SlicesDatabaseUtilsTest.java rename to tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java index f22e85ffdff..10e4b7694f9 100644 --- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseUtilsTest.java +++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java @@ -20,9 +20,13 @@ import static com.android.settings.TestConfig.SDK_VERSION; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + import android.content.Context; import android.net.Uri; +import com.android.settings.R; import com.android.settings.TestConfig; import com.android.settings.core.BasePreferenceController; import com.android.settings.testutils.SettingsRobolectricTestRunner; @@ -37,7 +41,7 @@ import androidx.app.slice.Slice; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = SDK_VERSION) -public class SlicesDatabaseUtilsTest { +public class SliceBuilderUtilsTest { private final String KEY = "KEY"; private final String TITLE = "title"; @@ -65,17 +69,74 @@ public class SlicesDatabaseUtilsTest { @Test public void testGetPreferenceController_buildsMatchingController() { - BasePreferenceController controller = SliceBuilderUtils.getPreferenceController(mContext, - getDummyData()); + BasePreferenceController controller = SliceBuilderUtils.getPreferenceController( + mContext, getDummyData()); assertThat(controller).isInstanceOf(FakeToggleController.class); } + @Test + public void testDynamicSummary_returnsSliceSummary() { + SliceData data = getDummyData(); + FakePreferenceController controller = new FakePreferenceController(mContext, KEY); + + String summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data); + + assertThat(summary).isEqualTo(data.getSummary()); + } + + @Test + public void testDynamicSummary_returnsFragmentSummary() { + SliceData data = getDummyData(null); + FakePreferenceController controller = spy(new FakePreferenceController(mContext, KEY)); + String controllerSummary = "new_Summary"; + doReturn(controllerSummary).when(controller).getSummary(); + + String summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data); + + assertThat(summary).isEqualTo(controllerSummary); + } + + @Test + public void testDynamicSummary_returnsSliceScreenTitle() { + SliceData data = getDummyData(null); + FakePreferenceController controller = new FakePreferenceController(mContext, KEY); + + String summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data); + + assertThat(summary).isEqualTo(data.getScreenTitle()); + } + + @Test + public void testDynamicSummary_placeHolderString_returnsScreenTitle() { + SliceData data = getDummyData(mContext.getString(R.string.summary_placeholder)); + FakePreferenceController controller = new FakePreferenceController(mContext, KEY); + String summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data); + + assertThat(summary).isEqualTo(data.getScreenTitle()); + } + + @Test + public void testDynamicSummary_sliceDataAndFragmentPlaceholder_returnsSliceScreenTitle() { + String summaryPlaceholder = mContext.getString(R.string.summary_placeholder); + SliceData data = getDummyData(summaryPlaceholder); + FakePreferenceController controller = spy(new FakePreferenceController(mContext, KEY)); + doReturn(summaryPlaceholder).when(controller).getSummary(); + + String summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data); + + assertThat(summary).isEqualTo(data.getScreenTitle()); + } + private SliceData getDummyData() { + return getDummyData(SUMMARY); + } + + private SliceData getDummyData(String summary) { return new SliceData.Builder() .setKey(KEY) .setTitle(TITLE) - .setSummary(SUMMARY) + .setSummary(summary) .setScreenTitle(SCREEN_TITLE) .setIcon(ICON) .setFragmentName(FRAGMENT_NAME)