diff --git a/src/com/android/settings/notification/modes/CircularIconsPreference.java b/src/com/android/settings/notification/modes/CircularIconsPreference.java index 1ce34766fdc..e3cd94848b0 100644 --- a/src/com/android/settings/notification/modes/CircularIconsPreference.java +++ b/src/com/android/settings/notification/modes/CircularIconsPreference.java @@ -51,6 +51,8 @@ import java.util.concurrent.Executor; public class CircularIconsPreference extends RestrictedPreference { + private static final float DISABLED_ITEM_ALPHA = 0.3f; + private Executor mUiExecutor; @Nullable private LinearLayout mIconContainer; @@ -98,6 +100,14 @@ public class CircularIconsPreference extends RestrictedPreference { displayIconsIfPending(); } + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if (mIconContainer != null) { + applyEnabledToIcons(mIconContainer, enabled); + } + } + private void displayIconsIfPending() { CircularIconSet pendingIconSet = mPendingDisplayIconSet; if (pendingIconSet != null) { @@ -211,6 +221,8 @@ public class CircularIconsPreference extends RestrictedPreference { textView.setText(getContext().getString(R.string.zen_mode_plus_n_items, extraItems)); } + applyEnabledToIcons(mIconContainer, isEnabled()); + // Display icons when all are ready (more consistent than randomly loading). mPendingLoadIconsFuture = Futures.allAsList(iconFutures); FutureUtil.whenDone( @@ -224,6 +236,13 @@ public class CircularIconsPreference extends RestrictedPreference { mUiExecutor); } + private void applyEnabledToIcons(ViewGroup container, boolean enabled) { + for (int i = 0; i < container.getChildCount(); i++) { + View child = container.getChildAt(i); + child.setAlpha(enabled ? 1.0f : DISABLED_ITEM_ALPHA); + } + } + private static Drawable getPlaceholderImage(Context context) { ShapeDrawable placeholder = new ShapeDrawable(new OvalShape()); placeholder.setTintList(Utils.getColorAttr(context, @@ -249,6 +268,18 @@ public class CircularIconsPreference extends RestrictedPreference { return parent.getChildAt(parent.getChildCount() - 1); } + @VisibleForTesting(otherwise = VisibleForTesting.NONE) + List getViews() { + if (mIconContainer == null) { + return List.of(); + } + ArrayList views = new ArrayList<>(); + for (int i = 0; i < mIconContainer.getChildCount(); i++) { + views.add(mIconContainer.getChildAt(i)); + } + return views; + } + @VisibleForTesting(otherwise = VisibleForTesting.NONE) List getIcons() { if (mIconContainer == null) { diff --git a/src/com/android/settings/notification/modes/InterruptionFilterPreferenceController.java b/src/com/android/settings/notification/modes/InterruptionFilterPreferenceController.java index 8bdeea40762..9d4a1725bcc 100644 --- a/src/com/android/settings/notification/modes/InterruptionFilterPreferenceController.java +++ b/src/com/android/settings/notification/modes/InterruptionFilterPreferenceController.java @@ -44,6 +44,7 @@ class InterruptionFilterPreferenceController extends AbstractZenModePreferenceCo @Override public void updateState(Preference preference, @NonNull ZenMode zenMode) { + preference.setEnabled(zenMode.isEnabled()); boolean filteringNotifications = zenMode.getRule().getInterruptionFilter() != INTERRUPTION_FILTER_ALL; ((TwoStatePreference) preference).setChecked(filteringNotifications); diff --git a/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java index 962e0162310..1521a8b4f09 100644 --- a/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java @@ -34,7 +34,6 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.Utils; -import com.android.settings.core.SubSettingLauncher; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.notification.modes.ZenMode; @@ -95,11 +94,11 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr Bundle bundle = new Bundle(); bundle.putString(EXTRA_AUTOMATIC_ZEN_RULE_ID, zenMode.getId()); // TODO(b/332937635): Update metrics category - preference.setIntent(new SubSettingLauncher(mContext) - .setDestination(ZenModeAppsFragment.class.getName()) - .setSourceMetricsCategory(0) - .setArguments(bundle) - .toIntent()); + preference.setIntent( + ZenSubSettingLauncher.forModeFragment(mContext, ZenModeAppsFragment.class, + zenMode.getId(), 0).toIntent()); + preference.setEnabled(zenMode.isEnabled()); + mZenMode = zenMode; mPreference = (CircularIconsPreference) preference; diff --git a/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceController.java index d3559f1cf5f..bba5e342732 100644 --- a/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceController.java @@ -24,7 +24,6 @@ import android.os.Bundle; import androidx.annotation.NonNull; import androidx.preference.Preference; -import com.android.settings.core.SubSettingLauncher; import com.android.settingslib.notification.modes.ZenMode; import com.android.settingslib.notification.modes.ZenModesBackend; @@ -43,11 +42,10 @@ class ZenModeDisplayLinkPreferenceController extends AbstractZenModePreferenceCo Bundle bundle = new Bundle(); bundle.putString(EXTRA_AUTOMATIC_ZEN_RULE_ID, zenMode.getId()); // TODO(b/332937635): Update metrics category - preference.setIntent(new SubSettingLauncher(mContext) - .setDestination(ZenModeDisplayFragment.class.getName()) - .setSourceMetricsCategory(0) - .setArguments(bundle) - .toIntent()); + preference.setIntent( + ZenSubSettingLauncher.forModeFragment(mContext, ZenModeDisplayFragment.class, + zenMode.getId(), 0).toIntent()); + preference.setEnabled(zenMode.isEnabled()); } @Override diff --git a/src/com/android/settings/notification/modes/ZenModeFragment.java b/src/com/android/settings/notification/modes/ZenModeFragment.java index 7d7631bef02..06612844dba 100644 --- a/src/com/android/settings/notification/modes/ZenModeFragment.java +++ b/src/com/android/settings/notification/modes/ZenModeFragment.java @@ -53,12 +53,15 @@ public class ZenModeFragment extends ZenModeFragmentBase { prefControllers.add(new ZenModeHeaderController(context, "header", this)); prefControllers.add( new ZenModeButtonPreferenceController(context, "activate", this, mBackend)); + prefControllers.add(new ZenModePreferenceCategoryController(context, "modes_filters")); prefControllers.add(new ZenModePeopleLinkPreferenceController( context, "zen_mode_people", mHelperBackend)); prefControllers.add(new ZenModeAppsLinkPreferenceController( context, "zen_mode_apps", this, mBackend, mHelperBackend)); prefControllers.add(new ZenModeOtherLinkPreferenceController( context, "zen_other_settings", mHelperBackend)); + prefControllers.add( + new ZenModePreferenceCategoryController(context, "modes_additional_actions")); prefControllers.add(new ZenModeDisplayLinkPreferenceController( context, "mode_display_settings", mBackend, mHelperBackend)); prefControllers.add(new ZenModeSetTriggerLinkPreferenceController(context, diff --git a/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java index d7bd5177aaf..15e0edcf1df 100644 --- a/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java @@ -70,6 +70,7 @@ class ZenModeOtherLinkPreferenceController extends AbstractZenModePreferenceCont ZenSubSettingLauncher.forModeFragment(mContext, ZenModeOtherFragment.class, zenMode.getId(), 0).toIntent()); + preference.setEnabled(zenMode.isEnabled()); preference.setSummary(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)); ((CircularIconsPreference) preference).displayIcons(getSoundIcons(zenMode.getPolicy())); } diff --git a/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceController.java index 762cdd57ca6..b5938c6d3ea 100644 --- a/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceController.java @@ -92,6 +92,7 @@ class ZenModePeopleLinkPreferenceController extends AbstractZenModePreferenceCon ZenSubSettingLauncher.forModeFragment(mContext, ZenModePeopleFragment.class, zenMode.getId(), 0).toIntent()); + preference.setEnabled(zenMode.isEnabled()); preference.setSummary(mSummaryHelper.getPeopleSummary(zenMode.getPolicy())); ((CircularIconsPreference) preference).displayIcons(getPeopleIcons(zenMode.getPolicy())); } diff --git a/src/com/android/settings/notification/modes/ZenModePreferenceCategoryController.java b/src/com/android/settings/notification/modes/ZenModePreferenceCategoryController.java new file mode 100644 index 00000000000..6ebcb1fd1f2 --- /dev/null +++ b/src/com/android/settings/notification/modes/ZenModePreferenceCategoryController.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 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.notification.modes; + +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.preference.Preference; + +import com.android.settingslib.notification.modes.ZenMode; + +/** + * Simple {@link AbstractZenModePreferenceController} used for all {@code PreferenceCategory} + * entries in {@link ZenModeFragment} that should be disabled when the mode is disabled. + */ +class ZenModePreferenceCategoryController extends AbstractZenModePreferenceController { + ZenModePreferenceCategoryController(@NonNull Context context, @NonNull String key) { + super(context, key); + } + + @Override + void updateState(Preference preference, @NonNull ZenMode zenMode) { + preference.setEnabled(zenMode.isEnabled()); + } +} diff --git a/tests/robotests/src/com/android/settings/notification/modes/CircularIconsPreferenceTest.java b/tests/robotests/src/com/android/settings/notification/modes/CircularIconsPreferenceTest.java index 73754df349b..ce23fc4ba05 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/CircularIconsPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/CircularIconsPreferenceTest.java @@ -226,4 +226,32 @@ public class CircularIconsPreferenceTest { mPreference.displayIcons(one); mPreference.displayIcons(same); // if no exception, wasn't called. } + + @Test + public void setEnabled_afterDisplayIcons_showsEnabledOrDisabledImages() { + CircularIconSet iconSet = new CircularIconSet<>(ImmutableList.of(1, 2), + ColorDrawable::new); + bindAndMeasureViewHolder(VIEW_WIDTH); + mPreference.displayIcons(iconSet); + assertThat(mPreference.getViews()).hasSize(2); + + mPreference.setEnabled(false); + assertThat(mPreference.getViews().get(0).getAlpha()).isLessThan(1f); + + mPreference.setEnabled(true); + assertThat(mPreference.getViews().get(0).getAlpha()).isEqualTo(1f); + } + + @Test + public void setEnabled_beforeDisplayIcons_showsEnabledOrDisabledImages() { + CircularIconSet iconSet = new CircularIconSet<>(ImmutableList.of(1, 2), + ColorDrawable::new); + + mPreference.setEnabled(false); + bindAndMeasureViewHolder(VIEW_WIDTH); + mPreference.displayIcons(iconSet); + + assertThat(mPreference.getViews()).hasSize(2); + assertThat(mPreference.getViews().get(0).getAlpha()).isLessThan(1f); + } } diff --git a/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java index 61d31929f4f..0c3f8e1815d 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/InterruptionFilterPreferenceControllerTest.java @@ -67,6 +67,18 @@ public final class InterruptionFilterPreferenceControllerTest { mController = new InterruptionFilterPreferenceController(mContext, "something", mBackend); } + @Test + public void testUpdateState_disabled() { + TwoStatePreference preference = mock(TwoStatePreference.class); + ZenMode zenMode = new TestModeBuilder() + .setEnabled(false) + .build(); + + mController.updateZenMode(preference, zenMode); + + verify(preference).setEnabled(false); + } + @Test public void testUpdateState_all() { TwoStatePreference preference = mock(TwoStatePreference.class); diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java index cc4d30643f7..301ff9092e0 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java @@ -141,6 +141,17 @@ public final class ZenModeAppsLinkPreferenceControllerTest { assertThat(mController.isAvailable()).isTrue(); } + @Test + public void testUpdateState_disabled() { + ZenMode zenMode = new TestModeBuilder() + .setEnabled(false) + .build(); + + mController.updateState(mPreference, zenMode); + + assertThat(mPreference.isEnabled()).isFalse(); + } + @Test public void testUpdateSetsIntent() { // Create a zen mode that allows priority channels to breakthrough. diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java index 6c3d74fed8e..29350f6737f 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeDisplayLinkPreferenceControllerTest.java @@ -28,6 +28,7 @@ import android.platform.test.flag.junit.SetFlagsRule; import androidx.preference.Preference; import com.android.settingslib.notification.modes.TestModeBuilder; +import com.android.settingslib.notification.modes.ZenMode; import com.android.settingslib.notification.modes.ZenModesBackend; import org.junit.Before; @@ -61,6 +62,18 @@ public final class ZenModeDisplayLinkPreferenceControllerTest { mContext, "something", mBackend, mHelperBackend); } + @Test + public void testUpdateState_disabled() { + Preference preference = mock(Preference.class); + ZenMode zenMode = new TestModeBuilder() + .setEnabled(false) + .build(); + + mController.updateState(preference, zenMode); + + verify(preference).setEnabled(false); + } + @Test @EnableFlags(Flags.FLAG_MODES_UI) public void testHasSummary() { diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java index 7fa4f9f0e71..8aa87e6c903 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java @@ -61,6 +61,18 @@ public final class ZenModeOtherLinkPreferenceControllerTest { mContext, "something", mHelperBackend); } + @Test + public void updateState_disabled() { + CircularIconsPreference pref = mock(CircularIconsPreference.class); + ZenMode zenMode = new TestModeBuilder() + .setEnabled(false) + .build(); + + mController.updateZenMode(pref, zenMode); + + verify(pref).setEnabled(false); + } + @Test public void updateState_loadsSummary() { CircularIconsPreference pref = mock(CircularIconsPreference.class); diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java index 8ec980d30aa..63068fa201f 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java @@ -111,6 +111,17 @@ public final class ZenModePeopleLinkPreferenceControllerTest { anyBoolean())).thenReturn(new ColorDrawable(Color.BLACK)); } + @Test + public void updateState_disabled() { + ZenMode zenMode = new TestModeBuilder() + .setEnabled(false) + .build(); + + mController.updateState(mPreference, zenMode); + + assertThat(mPreference.isEnabled()).isFalse(); + } + @Test public void updateState_setsSummary() { mController.updateState(mPreference, TestModeBuilder.EXAMPLE);