From 53f94f049574621ba10121165ef099b1c1c50279 Mon Sep 17 00:00:00 2001 From: Yuri Lin Date: Thu, 13 Mar 2025 19:06:24 -0400 Subject: [PATCH] Merge bundle global & type preference controllers. This change allows the combined preference controller to be a central place to manage dependencies between the global switch and the individual type checkboxes. When the last individual checkbox is unchecked, the global switch turns off as well. When the global switch is flipped, the individual type preferences become visible or invisible. Flag: android.service.notification.notification_classification Bug: 380291070 Test: atest BundleCombinedPreferenceControllerTest, manual Change-Id: I4e97d3d999c6114dd8c71100a0b0de1eb8f94e31 --- res/xml/bundle_notifications_settings.xml | 39 ++- .../BundleCombinedPreferenceController.java | 151 ++++++++++++ .../BundleGlobalPreferenceController.java | 60 ----- .../BundlePreferenceFragment.java | 20 +- .../BundleTypePreferenceController.java | 82 ------- .../notification/NotificationBackend.java | 13 + ...undleCombinedPreferenceControllerTest.java | 229 ++++++++++++++++++ .../BundleGlobalPreferenceControllerTest.java | 101 -------- .../BundleTypePreferenceControllerTest.java | 171 ------------- 9 files changed, 427 insertions(+), 439 deletions(-) create mode 100644 src/com/android/settings/notification/BundleCombinedPreferenceController.java delete mode 100644 src/com/android/settings/notification/BundleGlobalPreferenceController.java delete mode 100644 src/com/android/settings/notification/BundleTypePreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/notification/BundleCombinedPreferenceControllerTest.java delete mode 100644 tests/robotests/src/com/android/settings/notification/BundleGlobalPreferenceControllerTest.java delete mode 100644 tests/robotests/src/com/android/settings/notification/BundleTypePreferenceControllerTest.java diff --git a/res/xml/bundle_notifications_settings.xml b/res/xml/bundle_notifications_settings.xml index 3ff8c053273..0f153de81a6 100644 --- a/res/xml/bundle_notifications_settings.xml +++ b/res/xml/bundle_notifications_settings.xml @@ -32,30 +32,29 @@ settings:searchable="false" android:title="@string/notification_bundle_description"/> - + - + - + - + - + + + + ALL_PREF_TYPES = List.of(PROMO_KEY, NEWS_KEY, SOCIAL_KEY, RECS_KEY); + + @NonNull NotificationBackend mBackend; + + private @Nullable TwoStatePreference mGlobalPref; + private Map mTypePrefs = new ArrayMap<>(); + + public BundleCombinedPreferenceController(@NonNull Context context, @NonNull String prefKey, + @NonNull NotificationBackend backend) { + super(context, prefKey); + mBackend = backend; + } + + @Override + @AvailabilityStatus + public int getAvailabilityStatus() { + if (Flags.notificationClassificationUi() && mBackend.isNotificationBundlingSupported()) { + return AVAILABLE; + } + return CONDITIONALLY_UNAVAILABLE; + } + + @Override + public void updateState(Preference preference) { + PreferenceCategory category = (PreferenceCategory) preference; + + // Find and cache relevant preferences for later updates, then set values + mGlobalPref = category.findPreference(GLOBAL_KEY); + if (mGlobalPref != null) { + mGlobalPref.setOnPreferenceChangeListener(mGlobalPrefListener); + } + for (String key : ALL_PREF_TYPES) { + TwoStatePreference typePref = category.findPreference(key); + if (typePref != null) { + mTypePrefs.put(key, typePref); + typePref.setOnPreferenceChangeListener(getListenerForType(key)); + } + } + + updatePrefValues(); + } + + void updatePrefValues() { + boolean isBundlingEnabled = mBackend.isNotificationBundlingEnabled(mContext); + Set allowedTypes = mBackend.getAllowedBundleTypes(); + + // State check: if bundling is globally enabled, but there are no allowed bundle types, + // disable the global bundling state from here before proceeding. + if (isBundlingEnabled && allowedTypes.size() == 0) { + mBackend.setNotificationBundlingEnabled(false); + isBundlingEnabled = false; + } + + if (mGlobalPref != null) { + mGlobalPref.setChecked(isBundlingEnabled); + } + + for (String key : mTypePrefs.keySet()) { + TwoStatePreference typePref = mTypePrefs.get(key); + // checkboxes for individual types should only be active if the global switch is on + typePref.setVisible(isBundlingEnabled); + if (isBundlingEnabled) { + typePref.setChecked(allowedTypes.contains(getBundleTypeForKey(key))); + } + } + } + + private Preference.OnPreferenceChangeListener mGlobalPrefListener = (p, val) -> { + boolean checked = (boolean) val; + mBackend.setNotificationBundlingEnabled(checked); + // update state to hide or show preferences for individual types + updatePrefValues(); + return true; + }; + + // Returns a preference listener for the given pref key that: + // * sets the backend state for whether that type is enabled + // * if it is disabled, trigger a new update sync global switch if needed + private Preference.OnPreferenceChangeListener getListenerForType(String prefKey) { + return (p, val) -> { + boolean checked = (boolean) val; + mBackend.setBundleTypeState(getBundleTypeForKey(prefKey), checked); + if (!checked) { + // goes from checked to un-checked; update state in case this was the last enabled + // individual category + updatePrefValues(); + } + return true; + }; + } + + static @Adjustment.Types int getBundleTypeForKey(String preferenceKey) { + if (PROMO_KEY.equals(preferenceKey)) { + return Adjustment.TYPE_PROMOTION; + } else if (NEWS_KEY.equals(preferenceKey)) { + return Adjustment.TYPE_NEWS; + } else if (SOCIAL_KEY.equals(preferenceKey)) { + return Adjustment.TYPE_SOCIAL_MEDIA; + } else if (RECS_KEY.equals(preferenceKey)) { + return Adjustment.TYPE_CONTENT_RECOMMENDATION; + } + return Adjustment.TYPE_OTHER; + } + +} diff --git a/src/com/android/settings/notification/BundleGlobalPreferenceController.java b/src/com/android/settings/notification/BundleGlobalPreferenceController.java deleted file mode 100644 index 4df36ca716c..00000000000 --- a/src/com/android/settings/notification/BundleGlobalPreferenceController.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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; - -import android.app.Flags; -import android.content.Context; - -import androidx.annotation.NonNull; - -import com.android.settings.core.TogglePreferenceController; - -public class BundleGlobalPreferenceController extends TogglePreferenceController { - - NotificationBackend mBackend; - - public BundleGlobalPreferenceController(@NonNull Context context, - @NonNull String preferenceKey) { - super(context, preferenceKey); - mBackend = new NotificationBackend(); - } - - @Override - public int getAvailabilityStatus() { - if (Flags.notificationClassificationUi() && mBackend.isNotificationBundlingSupported()) { - return AVAILABLE; - } - return CONDITIONALLY_UNAVAILABLE; - } - - @Override - public boolean isChecked() { - return mBackend.isNotificationBundlingEnabled(mContext); - } - - @Override - public boolean setChecked(boolean isChecked) { - mBackend.setNotificationBundlingEnabled(isChecked); - return true; - } - - @Override - public int getSliceHighlightMenuRes() { - // not needed since it's not sliceable - return NO_RES; - } -} diff --git a/src/com/android/settings/notification/BundlePreferenceFragment.java b/src/com/android/settings/notification/BundlePreferenceFragment.java index 4a61f9e54af..fe854a7f6bc 100644 --- a/src/com/android/settings/notification/BundlePreferenceFragment.java +++ b/src/com/android/settings/notification/BundlePreferenceFragment.java @@ -16,24 +16,23 @@ package com.android.settings.notification; -import static android.service.notification.Adjustment.KEY_SUMMARIZATION; import static android.service.notification.Adjustment.KEY_TYPE; import android.app.Activity; import android.app.Application; +import android.app.Flags; import android.app.settings.SettingsEnums; import android.content.Context; -import android.app.Flags; - -import androidx.lifecycle.Lifecycle; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.applications.ApplicationsState; +import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.search.SearchIndexable; -import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; /** * Fragment for bundled notifications. @@ -41,6 +40,8 @@ import org.jetbrains.annotations.NotNull; @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) public class BundlePreferenceFragment extends DashboardFragment { + private static final String BUNDLE_CATEGORY_KEY = "enabled_settings"; + @Override public int getMetricsCategory() { return SettingsEnums.BUNDLED_NOTIFICATIONS; @@ -50,6 +51,15 @@ public class BundlePreferenceFragment extends DashboardFragment { protected int getPreferenceScreenResId() { return R.xml.bundle_notifications_settings; } + + @Override + protected List createPreferenceControllers(Context context) { + final List controllers = new ArrayList<>(); + controllers.add(new BundleCombinedPreferenceController(context, BUNDLE_CATEGORY_KEY, + new NotificationBackend())); + return controllers; + } + @Override protected String getLogTag() { return "BundlePreferenceFragment"; diff --git a/src/com/android/settings/notification/BundleTypePreferenceController.java b/src/com/android/settings/notification/BundleTypePreferenceController.java deleted file mode 100644 index d0786931ed7..00000000000 --- a/src/com/android/settings/notification/BundleTypePreferenceController.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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; - -import android.app.Flags; -import android.content.Context; -import android.service.notification.Adjustment; - -import androidx.annotation.NonNull; - -import com.android.settings.core.TogglePreferenceController; - -public class BundleTypePreferenceController extends TogglePreferenceController { - - static final String PROMO_KEY = "promotions"; - static final String NEWS_KEY = "news"; - static final String SOCIAL_KEY = "social"; - static final String RECS_KEY = "recs"; - - NotificationBackend mBackend; - int mType; - - public BundleTypePreferenceController(@NonNull Context context, - @NonNull String preferenceKey) { - super(context, preferenceKey); - mBackend = new NotificationBackend(); - mType = getBundleTypeForKey(); - } - - @Override - public int getAvailabilityStatus() { - if (Flags.notificationClassificationUi() && mBackend.isNotificationBundlingSupported() - && mBackend.isNotificationBundlingEnabled(mContext)) { - return AVAILABLE; - } - return CONDITIONALLY_UNAVAILABLE; - } - - @Override - public boolean isChecked() { - return mBackend.isBundleTypeApproved(mType); - } - - @Override - public boolean setChecked(boolean isChecked) { - mBackend.setBundleTypeState(mType, isChecked); - return true; - } - - @Override - public int getSliceHighlightMenuRes() { - // not needed since it's not sliceable - return NO_RES; - } - - private @Adjustment.Types int getBundleTypeForKey() { - if (PROMO_KEY.equals(mPreferenceKey)) { - return Adjustment.TYPE_PROMOTION; - } else if (NEWS_KEY.equals(mPreferenceKey)) { - return Adjustment.TYPE_NEWS; - } else if (SOCIAL_KEY.equals(mPreferenceKey)) { - return Adjustment.TYPE_SOCIAL_MEDIA; - } else if (RECS_KEY.equals(mPreferenceKey)) { - return Adjustment.TYPE_CONTENT_RECOMMENDATION; - } - return Adjustment.TYPE_OTHER; - } -} diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java index 31972edcc1f..45bf9e3e23a 100644 --- a/src/com/android/settings/notification/NotificationBackend.java +++ b/src/com/android/settings/notification/NotificationBackend.java @@ -751,6 +751,19 @@ public class NotificationBackend { return false; } + public Set getAllowedBundleTypes() { + try { + Set allowed = new HashSet<>(); + for (int type : sINM.getAllowedAdjustmentKeyTypes()) { + allowed.add(type); + } + return allowed; + } catch (Exception e) { + Log.w(TAG, "Error calling NoMan", e); + return new HashSet<>(); + } + } + public void setBundleTypeState(@Adjustment.Types int type, boolean enabled) { try { sINM.setAssistantAdjustmentKeyTypeState(type, enabled); diff --git a/tests/robotests/src/com/android/settings/notification/BundleCombinedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BundleCombinedPreferenceControllerTest.java new file mode 100644 index 00000000000..6d1c2c99a36 --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/BundleCombinedPreferenceControllerTest.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2025 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; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Flags; +import android.content.Context; +import android.os.RemoteException; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; +import android.service.notification.Adjustment; + +import androidx.preference.CheckBoxPreference; +import androidx.preference.PreferenceCategory; + +import com.android.settingslib.widget.MainSwitchPreference; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +import java.util.Set; + +@RunWith(RobolectricTestRunner.class) +@EnableFlags(android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION) +public class BundleCombinedPreferenceControllerTest { + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + + private static final String PREFERENCE_KEY = "preference_key"; + + private Context mContext; + private BundleCombinedPreferenceController mController; + + @Mock + private NotificationBackend mBackend; + + @Mock + private PreferenceCategory mPrefCategory; + + private MainSwitchPreference mGlobalSwitch; + private CheckBoxPreference mPromoCheckbox, mNewsCheckbox, mSocialCheckbox, mRecsCheckbox; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = RuntimeEnvironment.getApplication(); + mController = new BundleCombinedPreferenceController(mContext, PREFERENCE_KEY, mBackend); + + // preference category/controller initiation + mGlobalSwitch = new MainSwitchPreference(mContext); + when(mPrefCategory.findPreference( + BundleCombinedPreferenceController.GLOBAL_KEY)).thenReturn(mGlobalSwitch); + mPromoCheckbox = new CheckBoxPreference(mContext); + when(mPrefCategory.findPreference(BundleCombinedPreferenceController.PROMO_KEY)).thenReturn( + mPromoCheckbox); + mNewsCheckbox = new CheckBoxPreference(mContext); + when(mPrefCategory.findPreference(BundleCombinedPreferenceController.NEWS_KEY)).thenReturn( + mNewsCheckbox); + mSocialCheckbox = new CheckBoxPreference(mContext); + when(mPrefCategory.findPreference( + BundleCombinedPreferenceController.SOCIAL_KEY)).thenReturn(mSocialCheckbox); + mRecsCheckbox = new CheckBoxPreference(mContext); + when(mPrefCategory.findPreference(BundleCombinedPreferenceController.RECS_KEY)).thenReturn( + mRecsCheckbox); + + mController.updateState(mPrefCategory); + } + + @Test + @EnableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI) + public void isAvailable_flagEnabledNasSupports_shouldReturnTrue() { + when(mBackend.isNotificationBundlingSupported()).thenReturn(true); + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI) + public void isAvailable_flagEnabledNasDoesNotSupport_shouldReturnFalse() + throws RemoteException { + when(mBackend.isNotificationBundlingSupported()).thenReturn(false); + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + @DisableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI) + public void isAvailable_flagDisabledNasSupports_shouldReturnFalse() throws RemoteException { + when(mBackend.isNotificationBundlingSupported()).thenReturn(true); + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + @EnableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI) + public void updatePrefValues_reflectsSettings() { + // bundling is enabled globally + when(mBackend.isNotificationBundlingEnabled(any())).thenReturn(true); + + // allowed key types are promos & news + when(mBackend.getAllowedBundleTypes()).thenReturn(Set.of(Adjustment.TYPE_PROMOTION, + Adjustment.TYPE_NEWS)); + + mController.updatePrefValues(); + assertThat(mGlobalSwitch.isChecked()).isTrue(); + assertThat(mPromoCheckbox.isChecked()).isTrue(); + assertThat(mNewsCheckbox.isChecked()).isTrue(); + assertThat(mRecsCheckbox.isChecked()).isFalse(); + assertThat(mSocialCheckbox.isChecked()).isFalse(); + } + + @Test + @EnableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI) + public void updatePrefValues_typesGoneWhenGlobalOff() { + when(mBackend.isNotificationBundlingEnabled(any())).thenReturn(false); + when(mBackend.getAllowedBundleTypes()).thenReturn(Set.of(Adjustment.TYPE_PROMOTION, + Adjustment.TYPE_NEWS)); + + mController.updatePrefValues(); + assertThat(mGlobalSwitch.isChecked()).isFalse(); + assertThat(mPromoCheckbox.isVisible()).isFalse(); + assertThat(mNewsCheckbox.isVisible()).isFalse(); + assertThat(mRecsCheckbox.isVisible()).isFalse(); + assertThat(mSocialCheckbox.isVisible()).isFalse(); + } + + @Test + @EnableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI) + public void turnOffGlobalSwitch_updatesBackendAndTypeSwitches() { + // Initial state: global allowed + some types set + when(mBackend.isNotificationBundlingEnabled(any())).thenReturn(true); + when(mBackend.getAllowedBundleTypes()).thenReturn(Set.of(Adjustment.TYPE_PROMOTION, + Adjustment.TYPE_NEWS)); + mController.updatePrefValues(); + + // Simulate the global switch turning off. This also requires telling the mock backend to + // start returning false before the click listener updates pref values + when(mBackend.isNotificationBundlingEnabled(any())).thenReturn(false); + mGlobalSwitch.getOnPreferenceChangeListener().onPreferenceChange(mGlobalSwitch, false); + verify(mBackend, times(1)).setNotificationBundlingEnabled(false); + + // All individual type checkboxes should now not be visible. + assertThat(mPromoCheckbox.isVisible()).isFalse(); + assertThat(mNewsCheckbox.isVisible()).isFalse(); + assertThat(mRecsCheckbox.isVisible()).isFalse(); + assertThat(mSocialCheckbox.isVisible()).isFalse(); + } + + @Test + @EnableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI) + public void turnOnGlobalSwitch_updatesBackendAndTypeSwitches() { + when(mBackend.isNotificationBundlingEnabled(any())).thenReturn(false); + when(mBackend.getAllowedBundleTypes()).thenReturn(Set.of(Adjustment.TYPE_PROMOTION, + Adjustment.TYPE_NEWS)); + mController.updatePrefValues(); + + when(mBackend.isNotificationBundlingEnabled(any())).thenReturn(true); + mGlobalSwitch.getOnPreferenceChangeListener().onPreferenceChange(mGlobalSwitch, true); + verify(mBackend, times(1)).setNotificationBundlingEnabled(true); + + // type checkboxes should now exist & be checked accordingly to their state + assertThat(mPromoCheckbox.isChecked()).isTrue(); + assertThat(mNewsCheckbox.isChecked()).isTrue(); + assertThat(mRecsCheckbox.isChecked()).isFalse(); + assertThat(mSocialCheckbox.isChecked()).isFalse(); + } + + @Test + @EnableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI) + public void turnOnTypeBundle_updatesBackend_doesNotChangeGlobalSwitch() { + when(mBackend.isNotificationBundlingEnabled(any())).thenReturn(true); + when(mBackend.getAllowedBundleTypes()).thenReturn(Set.of(Adjustment.TYPE_SOCIAL_MEDIA)); + mController.updatePrefValues(); + + mRecsCheckbox.getOnPreferenceChangeListener().onPreferenceChange(mRecsCheckbox, true); + + // recs bundle setting should be updated in the backend, and global switch unchanged + verify(mBackend).setBundleTypeState(Adjustment.TYPE_CONTENT_RECOMMENDATION, true); + verify(mBackend, never()).setNotificationBundlingEnabled(anyBoolean()); + } + + @Test + @EnableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI) + public void turnOffTypeBundle_lastOneChangesGlobalSwitch() { + when(mBackend.isNotificationBundlingEnabled(any())).thenReturn(true); + when(mBackend.getAllowedBundleTypes()).thenReturn(Set.of(Adjustment.TYPE_SOCIAL_MEDIA, + Adjustment.TYPE_CONTENT_RECOMMENDATION)); + mController.updatePrefValues(); + + // Turning off one should update state, but not turn off the global setting + when(mBackend.getAllowedBundleTypes()).thenReturn(Set.of(Adjustment.TYPE_SOCIAL_MEDIA)); + mRecsCheckbox.getOnPreferenceChangeListener().onPreferenceChange(mRecsCheckbox, false); + verify(mBackend).setBundleTypeState(Adjustment.TYPE_CONTENT_RECOMMENDATION, false); + + // Now turn off the second + when(mBackend.getAllowedBundleTypes()).thenReturn(Set.of()); + mSocialCheckbox.getOnPreferenceChangeListener().onPreferenceChange(mSocialCheckbox, false); + verify(mBackend).setBundleTypeState(Adjustment.TYPE_SOCIAL_MEDIA, false); + + // This update should trigger a call to turn off the global switch + verify(mBackend).setNotificationBundlingEnabled(false); + } +} diff --git a/tests/robotests/src/com/android/settings/notification/BundleGlobalPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BundleGlobalPreferenceControllerTest.java deleted file mode 100644 index c389247389f..00000000000 --- a/tests/robotests/src/com/android/settings/notification/BundleGlobalPreferenceControllerTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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; - -import static android.service.notification.Adjustment.KEY_IMPORTANCE; -import static android.service.notification.Adjustment.KEY_TYPE; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.Flags; -import android.app.INotificationManager; -import android.content.Context; -import android.platform.test.flag.junit.SetFlagsRule; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -import java.util.List; - -@RunWith(RobolectricTestRunner.class) -public class BundleGlobalPreferenceControllerTest { - @Rule - public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); - - private static final String PREFERENCE_KEY = "preference_key"; - - private Context mContext; - BundleGlobalPreferenceController mController; - @Mock - INotificationManager mInm; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; - mSetFlagsRule.enableFlags( - android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION, - Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI); - mController = new BundleGlobalPreferenceController(mContext, PREFERENCE_KEY); - mController.mBackend.setNm(mInm); - } - - @Test - public void isAvailable_flagEnabledNasSupports_shouldReturnTrue() { - assertThat(mController.isAvailable()).isTrue(); - } - - @Test - public void isAvailable_flagEnabledNasDoesNotSupport_shouldReturnFalse() throws Exception { - when(mInm.getUnsupportedAdjustmentTypes()).thenReturn(List.of(KEY_TYPE)); - assertThat(mController.isAvailable()).isFalse(); - } - - @Test - public void isAvailable_flagDisabledNasSupports_shouldReturnFalse() { - mSetFlagsRule.disableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI); - assertThat(mController.isAvailable()).isFalse(); - } - - @Test - public void isChecked() throws Exception { - when(mInm.getAllowedAssistantAdjustments(any())).thenReturn(List.of(KEY_TYPE)); - assertThat(mController.isChecked()).isTrue(); - - when(mInm.getAllowedAssistantAdjustments(any())).thenReturn(List.of(KEY_IMPORTANCE)); - assertThat(mController.isChecked()).isFalse(); - } - - @Test - public void setChecked() throws Exception { - mController.setChecked(false); - verify(mInm).disallowAssistantAdjustment(KEY_TYPE); - - mController.setChecked(true); - verify(mInm).allowAssistantAdjustment(KEY_TYPE); - } -} diff --git a/tests/robotests/src/com/android/settings/notification/BundleTypePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BundleTypePreferenceControllerTest.java deleted file mode 100644 index 68bb1bb276e..00000000000 --- a/tests/robotests/src/com/android/settings/notification/BundleTypePreferenceControllerTest.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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; - -import static android.service.notification.Adjustment.KEY_TYPE; -import static android.service.notification.Adjustment.TYPE_CONTENT_RECOMMENDATION; -import static android.service.notification.Adjustment.TYPE_NEWS; -import static android.service.notification.Adjustment.TYPE_PROMOTION; -import static android.service.notification.Adjustment.TYPE_SOCIAL_MEDIA; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.Flags; -import android.app.INotificationManager; -import android.content.Context; -import android.os.RemoteException; -import android.platform.test.flag.junit.SetFlagsRule; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -import java.util.List; - -@RunWith(RobolectricTestRunner.class) -public class BundleTypePreferenceControllerTest { - @Rule - public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); - - private static final String PREFERENCE_KEY = "preference_key"; - - private Context mContext; - BundleTypePreferenceController mController; - @Mock - INotificationManager mInm; - - @Before - public void setUp() throws RemoteException { - MockitoAnnotations.initMocks(this); - when(mInm.getAllowedAssistantAdjustments(any())).thenReturn(List.of(KEY_TYPE)); - when(mInm.getUnsupportedAdjustmentTypes()).thenReturn(List.of()); - mSetFlagsRule.enableFlags( - android.service.notification.Flags.FLAG_NOTIFICATION_CLASSIFICATION, - Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI); - mContext = RuntimeEnvironment.application; - mController = new BundleTypePreferenceController(mContext, PREFERENCE_KEY); - mController.mBackend.setNm(mInm); - } - - @Test - public void isAvailable() throws RemoteException { - when(mInm.getAllowedAssistantAdjustments(any())).thenReturn(List.of(KEY_TYPE)); - assertThat(mController.isAvailable()).isTrue(); - } - - @Test - public void isAvailable_flagEnabledNasDoesNotSupport_shouldReturnFalse() - throws RemoteException { - when(mInm.getUnsupportedAdjustmentTypes()).thenReturn(List.of(KEY_TYPE)); - when(mInm.getAllowedAssistantAdjustments(any())).thenReturn(List.of(KEY_TYPE)); - assertThat(mController.isAvailable()).isFalse(); - } - - @Test - public void isAvailable_flagDisabledNasSupports_shouldReturnFalse() throws RemoteException { - mSetFlagsRule.disableFlags(Flags.FLAG_NOTIFICATION_CLASSIFICATION_UI); - when(mInm.getUnsupportedAdjustmentTypes()).thenReturn(List.of()); - when(mInm.getAllowedAssistantAdjustments(any())).thenReturn(List.of(KEY_TYPE)); - assertThat(mController.isAvailable()).isFalse(); - } - - @Test - public void isAvailable_flagEnabledNasDisabled_shouldReturnFalse() throws RemoteException { - when(mInm.getUnsupportedAdjustmentTypes()).thenReturn(List.of()); - when(mInm.getAllowedAssistantAdjustments(any())).thenReturn(List.of()); - assertThat(mController.isAvailable()).isFalse(); - } - - @Test - public void isChecked_promotions() throws RemoteException { - mController = new BundleTypePreferenceController(mContext, - BundleTypePreferenceController.PROMO_KEY); - - when(mInm.getAllowedAdjustmentKeyTypes()).thenReturn(new int[]{TYPE_PROMOTION}); - assertThat(mController.isChecked()).isTrue(); - - when(mInm.getAllowedAdjustmentKeyTypes()).thenReturn(new int[]{}); - assertThat(mController.isChecked()).isFalse(); - } - - @Test - public void isChecked_news() throws RemoteException { - mController = new BundleTypePreferenceController(mContext, - BundleTypePreferenceController.NEWS_KEY); - - when(mInm.getAllowedAdjustmentKeyTypes()).thenReturn(new int[]{TYPE_NEWS}); - assertThat(mController.isChecked()).isTrue(); - - when(mInm.getAllowedAdjustmentKeyTypes()).thenReturn(new int[]{}); - assertThat(mController.isChecked()).isFalse(); - } - - @Test - public void isChecked_social() throws RemoteException { - mController = new BundleTypePreferenceController(mContext, - BundleTypePreferenceController.SOCIAL_KEY); - - when(mInm.getAllowedAdjustmentKeyTypes()).thenReturn(new int[]{TYPE_SOCIAL_MEDIA}); - assertThat(mController.isChecked()).isTrue(); - - when(mInm.getAllowedAdjustmentKeyTypes()).thenReturn(new int[]{}); - assertThat(mController.isChecked()).isFalse(); - } - - @Test - public void isChecked_recs() throws RemoteException { - mController = new BundleTypePreferenceController(mContext, - BundleTypePreferenceController.RECS_KEY); - - when(mInm.getAllowedAdjustmentKeyTypes()).thenReturn( - new int[]{TYPE_CONTENT_RECOMMENDATION}); - assertThat(mController.isChecked()).isTrue(); - - when(mInm.getAllowedAdjustmentKeyTypes()).thenReturn(new int[]{}); - assertThat(mController.isChecked()).isFalse(); - } - - @Test - public void isChecked_mixed() throws RemoteException { - mController = new BundleTypePreferenceController(mContext, - BundleTypePreferenceController.RECS_KEY); - - when(mInm.getAllowedAdjustmentKeyTypes()).thenReturn( - new int[]{TYPE_PROMOTION, TYPE_CONTENT_RECOMMENDATION}); - assertThat(mController.isChecked()).isTrue(); - } - - @Test - public void setChecked() throws RemoteException { - mController = new BundleTypePreferenceController(mContext, - BundleTypePreferenceController.PROMO_KEY); - mController.setChecked(false); - verify(mInm).setAssistantAdjustmentKeyTypeState(TYPE_PROMOTION, false); - - mController.setChecked(true); - verify(mInm).setAssistantAdjustmentKeyTypeState(TYPE_PROMOTION, true); - } -}