diff --git a/res/values/strings.xml b/res/values/strings.xml
index b18002fc39b..f5a702338ef 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -10235,6 +10235,9 @@
Internet Connectivity
+
+ Volume
+
Force desktop mode
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index d38a8e4dc7c..ee8613d5fca 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -28,6 +28,7 @@
android:icon="@drawable/ic_media_stream"
android:title="@string/media_volume_option_title"
android:order="-180"
+ settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.notification.MediaVolumePreferenceController"/>
@@ -44,6 +45,7 @@
android:icon="@drawable/ic_local_phone_24_lib"
android:title="@string/call_volume_option_title"
android:order="-170"
+ settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.notification.CallVolumePreferenceController"/>
@@ -60,6 +62,7 @@
android:icon="@drawable/ic_notifications"
android:title="@string/ring_volume_option_title"
android:order="-160"
+ settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.notification.RingVolumePreferenceController"/>
@@ -69,6 +72,7 @@
android:icon="@*android:drawable/ic_audio_alarm"
android:title="@string/alarm_volume_option_title"
android:order="-150"
+ settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.notification.AlarmVolumePreferenceController"/>
diff --git a/src/com/android/settings/panel/InternetConnectivityPanel.java b/src/com/android/settings/panel/InternetConnectivityPanel.java
index 5b7bc3208bd..aae42f87e94 100644
--- a/src/com/android/settings/panel/InternetConnectivityPanel.java
+++ b/src/com/android/settings/panel/InternetConnectivityPanel.java
@@ -47,8 +47,8 @@ public class InternetConnectivityPanel implements PanelContent {
}
@Override
- public String getTitle() {
- return (String) mContext.getText(R.string.internet_connectivity_panel_title);
+ public CharSequence getTitle() {
+ return mContext.getText(R.string.internet_connectivity_panel_title);
}
@Override
diff --git a/src/com/android/settings/panel/PanelFeatureProviderImpl.java b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
index 2e840786b7f..503a5c37b6f 100644
--- a/src/com/android/settings/panel/PanelFeatureProviderImpl.java
+++ b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
@@ -25,6 +25,8 @@ public class PanelFeatureProviderImpl implements PanelFeatureProvider {
switch (panelType) {
case SettingsPanelActivity.PANEL_TYPE_WIFI:
return InternetConnectivityPanel.create(context);
+ case SettingsPanelActivity.PANEL_TYPE_VOLUME:
+ return VolumePanel.create(context);
}
throw new IllegalStateException("No matching panel for: " + panelType);
diff --git a/src/com/android/settings/panel/SettingsPanelActivity.java b/src/com/android/settings/panel/SettingsPanelActivity.java
index db1f60d3e49..09bead4c52e 100644
--- a/src/com/android/settings/panel/SettingsPanelActivity.java
+++ b/src/com/android/settings/panel/SettingsPanelActivity.java
@@ -54,6 +54,9 @@ public class SettingsPanelActivity extends FragmentActivity {
// TODO (b/117804442) move to framework
public static final String PANEL_TYPE_WIFI = "wifi_panel";
+ // TODO (b/117804442) move to framework
+ public static final String PANEL_TYPE_VOLUME = "volume_panel";
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java
new file mode 100644
index 00000000000..c0118d75290
--- /dev/null
+++ b/src/com/android/settings/panel/VolumePanel.java
@@ -0,0 +1,64 @@
+/*
+ * 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.panel;
+
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_ALARM_URI;
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_CALL_URI;
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_MEDIA_URI;
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_RINGER_URI;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import java.util.ArrayList;
+import java.util.List;
+
+public class VolumePanel implements PanelContent {
+
+ private final Context mContext;
+
+ public static VolumePanel create(Context context) {
+ return new VolumePanel(context);
+ }
+
+ private VolumePanel(Context context) {
+ mContext = context.getApplicationContext();
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return mContext.getText(R.string.volume_connectivity_panel_title);
+ }
+
+ @Override
+ public List getSlices() {
+ final List uris = new ArrayList<>();
+ uris.add(VOLUME_MEDIA_URI);
+ uris.add(VOLUME_CALL_URI);
+ uris.add(VOLUME_RINGER_URI);
+ uris.add(VOLUME_ALARM_URI);
+ return uris;
+ }
+
+ @Override
+ public Intent getSeeMoreIntent() {
+ return new Intent(Settings.ACTION_SOUND_SETTINGS);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index f2b3299ba1c..7ca92a946cc 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -25,6 +25,7 @@ import android.content.ContentResolver;
import android.net.Uri;
import android.provider.SettingsSlicesContract;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.wifi.calling.WifiCallingSliceHelper;
@@ -147,6 +148,43 @@ public class CustomSliceRegistry {
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath("storage_card")
.build();
+ /**
+ * Full {@link Uri} for the Alarm volume Slice.
+ */
+ public static final Uri VOLUME_ALARM_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("alarm_volume")
+ .build();
+ /**
+ * Full {@link Uri} for the Call Volume Slice.
+ */
+ public static final Uri VOLUME_CALL_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("call_volume")
+ .build();
+ /**
+ * Full {@link Uri} for the Media Volume Slice.
+ */
+ public static final Uri VOLUME_MEDIA_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("media_volume")
+ .build();
+ /**
+ * Full {@link Uri} for the Ringer volume Slice.
+ */
+ public static final Uri VOLUME_RINGER_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("ring_volume")
+ .build();
+
/**
* Full {@link Uri} for the Wifi Calling Slice.
*/
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index 76eefac9b1f..9201d03f192 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -193,8 +193,9 @@ public class SliceBuilderUtils {
CharSequence summaryText = controller.getSummary();
// Priority 1 : User prefers showing the dynamic summary in slice view rather than static
- // summary.
- if (isDynamicSummaryAllowed && isValidSummary(context, summaryText)) {
+ // summary. Note it doesn't require a valid summary - so we can force some slices to have
+ // empty summaries (ex: volume).
+ if (isDynamicSummaryAllowed) {
return summaryText;
}
diff --git a/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java b/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
index 9b29d486961..cf344d22834 100644
--- a/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
@@ -61,7 +61,6 @@ public class PanelFragmentTest {
mFakePanelContent = new FakePanelContent();
doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
-
ActivityController activityController =
Robolectric.buildActivity(FakeSettingsPanelActivity.class);
activityController.setup();
diff --git a/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
index bfd7863ace3..02a7d0aa013 100644
--- a/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
@@ -54,7 +54,13 @@ public class PanelSlicesAdapterTest {
public void setUp() {
mContext = RuntimeEnvironment.application;
- final ActivityController activityController =
+ mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
+ mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+ mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
+ mFakePanelContent = new FakePanelContent();
+ doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
+
+ ActivityController activityController =
Robolectric.buildActivity(FakeSettingsPanelActivity.class);
activityController.setup();
@@ -65,12 +71,6 @@ public class PanelSlicesAdapterTest {
.getSupportFragmentManager()
.findFragmentById(R.id.main_content));
- mPanelFeatureProvider = spy(new PanelFeatureProviderImpl());
- mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
- mFakeFeatureFactory.panelFeatureProvider = mPanelFeatureProvider;
- mFakePanelContent = new FakePanelContent();
- doReturn(mFakePanelContent).when(mPanelFeatureProvider).getPanel(any(), any());
-
mAdapter = new PanelSlicesAdapter(mPanelFragment, mFakePanelContent.getSlices());
}
diff --git a/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
new file mode 100644
index 00000000000..21019d355b7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.panel;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.Uri;
+
+import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class VolumePanelTest {
+
+ private VolumePanel mPanel;
+
+ @Before
+ public void setUp() {
+ mPanel = VolumePanel.create(RuntimeEnvironment.application);
+ }
+
+ @Test
+ public void getSlices_containsNecessarySlices() {
+ final List uris = mPanel.getSlices();
+
+ assertThat(uris).containsExactly(
+ CustomSliceRegistry.VOLUME_CALL_URI,
+ CustomSliceRegistry.VOLUME_MEDIA_URI,
+ CustomSliceRegistry.VOLUME_RINGER_URI,
+ CustomSliceRegistry.VOLUME_ALARM_URI);
+ }
+
+ @Test
+ public void getSeeMoreIntent_notNull() {
+ assertThat(mPanel.getSeeMoreIntent()).isNotNull();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 2e2104be7c0..f9937f4dd5a 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -217,6 +217,19 @@ public class SliceBuilderUtilsTest {
assertThat(summary).isEqualTo(controllerSummary);
}
+ @Test
+ public void getDynamicSummary_allowDynamicSummary_nullSummary_returnsNull() {
+ final SliceData data = getDummyData(true /*isDynamicSummaryAllowed*/);
+ final FakePreferenceController controller = spy(
+ new FakePreferenceController(mContext, KEY));
+ final String controllerSummary = null;
+ doReturn(controllerSummary).when(controller).getSummary();
+
+ final CharSequence summary = SliceBuilderUtils.getSubtitleText(mContext, controller, data);
+
+ assertThat(summary).isNull();
+ }
+
@Test
public void getDynamicSummary_returnsScreenTitle() {
final SliceData data = getDummyData();