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();