Loading res/xml/cellular_security.xml +5 −1 Original line number Diff line number Diff line Loading @@ -21,8 +21,11 @@ <com.android.settingslib.widget.TopIntroPreference android:key="cellular_security_prefs_top_intro" android:title="@string/cellular_security_top_intro"/> android:title="@string/cellular_security_top_intro" android:order="0"/> <PreferenceCategory android:order="5" android:key="cellular_security_notifications_category" android:title="@string/cellular_security_notifications" settings:controller="com.android.settings.network.telephony.CellularSecurityNotificationsDividerController"> Loading @@ -34,6 +37,7 @@ "com.android.settings.network.telephony.CellularSecurityNotificationsPreferenceController"/> </PreferenceCategory> <PreferenceCategory android:order="6" android:key="cellular_security_encryption_divider" android:title="@string/cellular_security_settings_encryption_title" settings:controller="com.android.settings.network.telephony.CellularSecurityEncryptionDividerController"> Loading src/com/android/settings/network/telephony/AdaptiveNetworkPreferenceController.java 0 → 100644 +145 −0 Original line number Diff line number Diff line /* * 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.network.telephony; import android.app.PendingIntent; import android.content.Context; import android.os.Build; import android.safetycenter.SafetyCenterManager; import android.safetycenter.SafetySourceData; import android.safetycenter.SafetySourceIssue; import android.safetycenter.SafetySourceIssue.Action; import android.telephony.TelephonyManager; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settingslib.widget.BannerMessagePreference; import com.android.settingslib.widget.BannerMessagePreference.AttentionLevel; /** * This controller for Cellular Security settings Screen, adds Cellular Security alerts for * Device ID Disclosure and Network encryption/unencryption to the screen. */ public class AdaptiveNetworkPreferenceController { private static final String TAG = "AdaptiveNetworkPreferenceController"; private static final String CELLULAR_SECURITY_SAFETY_SOURCE_ID = "AndroidCellularNetworkSecurity"; private static final String ACTION_LEARN_MORE_ID = "learn_more"; private final Context mContext; private @Nullable TelephonyManager mTelephonyManager; /** * Class constructor of "Cellular Security banner" preference. * * @param context of settings */ public AdaptiveNetworkPreferenceController(@NonNull Context context) { mContext = context; mTelephonyManager = context.getSystemService(TelephonyManager.class); } /** * Adds the controlled preference to the provided preference screen. */ public void addToScreen(@NonNull PreferenceScreen screen) { if (!areNotificationsEnabled()) { // Notification are not enabled for cellular security. return; } if (!isSafetyCenterSupported()) { // SafetyCenter is not supported on the device. return; } SafetyCenterManager safetyCenterManager = mContext.getSystemService( SafetyCenterManager.class); SafetySourceData data = safetyCenterManager.getSafetySourceData( CELLULAR_SECURITY_SAFETY_SOURCE_ID); if (data != null && !data.getIssues().isEmpty()) { for (SafetySourceIssue safetySourceIssue : data.getIssues()) { screen.addPreference(getBannerpreference(safetySourceIssue)); } } } private BannerMessagePreference getBannerpreference(SafetySourceIssue safetySourceIssue) { BannerMessagePreference preference = new BannerMessagePreference(mContext); preference.setOrder(1); preference.setTitle(safetySourceIssue.getTitle()); preference.setSummary(safetySourceIssue.getSummary()); preference.setAttentionLevel(getBannerAttentionLevel(safetySourceIssue.getSeverityLevel())); if (SafetySourceData.SEVERITY_LEVEL_INFORMATION == safetySourceIssue.getSeverityLevel()) { preference.setIcon(R.drawable.ic_info_selector); } for (Action action : safetySourceIssue.getActions()) { if (ACTION_LEARN_MORE_ID.equals(action.getId())) { preference.setNegativeButtonText(action.getLabel()); preference.setNegativeButtonOnClickListener(p -> openLearnMoreLink(action.getPendingIntent())); } } return preference; } @VisibleForTesting protected boolean areNotificationsEnabled() { if (mTelephonyManager == null) { Log.w(TAG, "Telephony manager not yet initialized"); return false; } return mTelephonyManager.isNullCipherNotificationsEnabled() && mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled(); } @VisibleForTesting protected boolean isSafetyCenterSupported() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { return false; } SafetyCenterManager safetyCenterManager = mContext.getSystemService( SafetyCenterManager.class); if (safetyCenterManager == null) { return false; } return safetyCenterManager.isSafetyCenterEnabled(); } private void openLearnMoreLink(PendingIntent intent) { if (intent != null) { mContext.startActivity(intent.getIntent()); } else { Log.w(TAG, "LearnMoreIntent is null"); } } private AttentionLevel getBannerAttentionLevel(int severityLevel) { switch (severityLevel) { case SafetySourceData.SEVERITY_LEVEL_INFORMATION: return AttentionLevel.LOW; case SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION: return AttentionLevel.MEDIUM; case SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING: return AttentionLevel.HIGH; default: return AttentionLevel.NORMAL; } } } src/com/android/settings/network/telephony/CellularSecuritySettingsFragment.java +18 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package com.android.settings.network.telephony; import android.app.settings.SettingsEnums; import android.content.Context; import android.os.Bundle; import androidx.annotation.NonNull; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; Loading @@ -28,6 +32,19 @@ public class CellularSecuritySettingsFragment extends DashboardFragment { private static final String TAG = "CellularSecuritySettingsFragment"; public static final String KEY_CELLULAR_SECURITY_PREFERENCE = "cellular_security"; private AdaptiveNetworkPreferenceController mAdaptiveNetworkPreferenceController; @Override public void onAttach(@NonNull Context context) { super.onAttach(context); mAdaptiveNetworkPreferenceController = new AdaptiveNetworkPreferenceController(context); } @Override public void onCreatePreferences(@NonNull Bundle savedInstanceState, @NonNull String rootKey) { super.onCreatePreferences(savedInstanceState, rootKey); mAdaptiveNetworkPreferenceController.addToScreen(getPreferenceScreen()); } @Override public int getMetricsCategory() { Loading tests/robotests/src/com/android/settings/network/telephony/AdaptiveNetworkPreferenceControllerTest.java 0 → 100644 +239 −0 Original line number Diff line number Diff line /* * 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.network.telephony; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.PendingIntent; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Build; import android.safetycenter.SafetyCenterManager; import android.safetycenter.SafetySourceData; import android.safetycenter.SafetySourceIssue; import android.telephony.TelephonyManager; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.settings.R; import com.android.settingslib.widget.BannerMessagePreference; import org.junit.Assume; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import java.util.ArrayList; import java.util.List; @RunWith(AndroidJUnit4.class) public class AdaptiveNetworkPreferenceControllerTest { private static final String CELLULAR_SECURITY_SAFETY_SOURCE_ID = "AndroidCellularNetworkSecurity"; private static final String IDENTIFIER_DISCLOSURE_ISSUE_ID = "identifier_disclosure"; private static final String ACTION_LEARN_MORE_ID = "learn_more"; @Mock private TelephonyManager mTelephonyManager; @Mock private SafetyCenterManager mSafetyCenterManager; @Mock private PreferenceScreen mPreferenceScreen; private Context mContext; private AdaptiveNetworkPreferenceController mController; @Before public void setUp() { MockitoAnnotations.initMocks(this); // Tests must be skipped if these conditions aren't met as they cannot be mocked Assume.assumeTrue(Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU); mContext = spy(ApplicationProvider.getApplicationContext()); when(mContext.getSystemService(SafetyCenterManager.class)).thenReturn(mSafetyCenterManager); when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); mController = new AdaptiveNetworkPreferenceController(mContext); } @Test public void addToScreen_telephonyManagerNotInit() { when(mContext.getSystemService(TelephonyManager.class)).thenReturn(null); mController.addToScreen(mPreferenceScreen); verify(mPreferenceScreen, never()).addPreference(any(BannerMessagePreference.class)); } @Test public void addToScreen_safetyCenterManagerNotInit() { when(mTelephonyManager.isNullCipherNotificationsEnabled()).thenReturn(true); when(mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled()).thenReturn( true); when(mContext.getSystemService(SafetyCenterManager.class)).thenReturn(null); mController.addToScreen(mPreferenceScreen); verify(mPreferenceScreen, never()).addPreference(any(BannerMessagePreference.class)); } @Test public void addToScreen_SafetySourceData_issuesIsEmpty() { when(mSafetyCenterManager.isSafetyCenterEnabled()).thenReturn(true); when(mTelephonyManager.isNullCipherNotificationsEnabled()).thenReturn(true); when(mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled()).thenReturn( true); SafetySourceData data = mock(SafetySourceData.class); when(data.getIssues()).thenReturn(new ArrayList<SafetySourceIssue>()); when(mSafetyCenterManager.getSafetySourceData( CELLULAR_SECURITY_SAFETY_SOURCE_ID)).thenReturn(data); mController.addToScreen(mPreferenceScreen); verify(mPreferenceScreen, never()).addPreference(any(BannerMessagePreference.class)); } @Test public void addToScreen_bannerMessagePreference() { String learMoreTitle = "Learn More"; String IssueTitle = "Title"; String IssueSummary = "Summary"; when(mSafetyCenterManager.isSafetyCenterEnabled()).thenReturn(true); when(mTelephonyManager.isNullCipherNotificationsEnabled()).thenReturn(true); when(mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled()).thenReturn( true); SafetySourceData data = mock(SafetySourceData.class); PendingIntent pendIntent = mock(PendingIntent.class); List<SafetySourceIssue> issues = new ArrayList<>(); SafetySourceIssue.Builder builder = new SafetySourceIssue.Builder( "1", IssueTitle, IssueSummary, SafetySourceData.SEVERITY_LEVEL_INFORMATION, IDENTIFIER_DISCLOSURE_ISSUE_ID); builder.addAction(new SafetySourceIssue.Action.Builder( ACTION_LEARN_MORE_ID, learMoreTitle, pendIntent).build()); issues.add(builder.build()); when(data.getIssues()).thenReturn(issues); when(mSafetyCenterManager.getSafetySourceData( CELLULAR_SECURITY_SAFETY_SOURCE_ID)).thenReturn(data); Drawable drawable = mock(Drawable.class); when(mContext.getDrawable(R.drawable.ic_info_selector)).thenReturn(drawable); BannerMessagePreference[] capturedObject = new BannerMessagePreference[1]; doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { capturedObject[0] = (BannerMessagePreference) invocation.getArguments()[0]; return null; } }).when(mPreferenceScreen).addPreference(any(BannerMessagePreference.class)); mController.addToScreen(mPreferenceScreen); assertThat(capturedObject[0].getOrder()).isEqualTo(1); assertTrue(capturedObject[0].getTitle().toString().contentEquals(IssueTitle)); assertTrue(capturedObject[0].getSummary().toString().contentEquals(IssueSummary)); assertThat(capturedObject[0].getIcon()).isEqualTo(drawable); verify(mPreferenceScreen).addPreference(any(BannerMessagePreference.class)); } @Test public void isSafetyCenterSupported_safetyCenterManagerNotInit() { when(mContext.getSystemService(SafetyCenterManager.class)).thenReturn(null); boolean result = mController.isSafetyCenterSupported(); assertFalse(result); } @Test public void isSafetyCenterSupported_disable() { when(mSafetyCenterManager.isSafetyCenterEnabled()).thenReturn(false); boolean result = mController.isSafetyCenterSupported(); assertFalse(result); } @Test public void isSafetyCenterSupported_enable() { when(mSafetyCenterManager.isSafetyCenterEnabled()).thenReturn(true); boolean result = mController.isSafetyCenterSupported(); assertTrue(result); } @Test public void areNotificationsEnabled_telephonyManagerNotInit() { when(mContext.getSystemService(TelephonyManager.class)).thenReturn(null); boolean result = mController.areNotificationsEnabled(); assertFalse(result); } @Test public void areNotificationsEnabled_telephonyManagerNullCipherDisable() { when(mTelephonyManager.isNullCipherNotificationsEnabled()).thenReturn(false); boolean result = mController.areNotificationsEnabled(); assertFalse(result); } @Test public void areNotificationsEnabled_telephonyManagerIdenfierDiscosureDisable() { when(mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled()).thenReturn( false); boolean result = mController.areNotificationsEnabled(); assertFalse(result); } @Test public void areNotificationsEnabled_enable() { when(mTelephonyManager.isNullCipherNotificationsEnabled()).thenReturn( true); when(mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled()).thenReturn( true); boolean result = mController.areNotificationsEnabled(); assertTrue(result); } } Loading
res/xml/cellular_security.xml +5 −1 Original line number Diff line number Diff line Loading @@ -21,8 +21,11 @@ <com.android.settingslib.widget.TopIntroPreference android:key="cellular_security_prefs_top_intro" android:title="@string/cellular_security_top_intro"/> android:title="@string/cellular_security_top_intro" android:order="0"/> <PreferenceCategory android:order="5" android:key="cellular_security_notifications_category" android:title="@string/cellular_security_notifications" settings:controller="com.android.settings.network.telephony.CellularSecurityNotificationsDividerController"> Loading @@ -34,6 +37,7 @@ "com.android.settings.network.telephony.CellularSecurityNotificationsPreferenceController"/> </PreferenceCategory> <PreferenceCategory android:order="6" android:key="cellular_security_encryption_divider" android:title="@string/cellular_security_settings_encryption_title" settings:controller="com.android.settings.network.telephony.CellularSecurityEncryptionDividerController"> Loading
src/com/android/settings/network/telephony/AdaptiveNetworkPreferenceController.java 0 → 100644 +145 −0 Original line number Diff line number Diff line /* * 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.network.telephony; import android.app.PendingIntent; import android.content.Context; import android.os.Build; import android.safetycenter.SafetyCenterManager; import android.safetycenter.SafetySourceData; import android.safetycenter.SafetySourceIssue; import android.safetycenter.SafetySourceIssue.Action; import android.telephony.TelephonyManager; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settingslib.widget.BannerMessagePreference; import com.android.settingslib.widget.BannerMessagePreference.AttentionLevel; /** * This controller for Cellular Security settings Screen, adds Cellular Security alerts for * Device ID Disclosure and Network encryption/unencryption to the screen. */ public class AdaptiveNetworkPreferenceController { private static final String TAG = "AdaptiveNetworkPreferenceController"; private static final String CELLULAR_SECURITY_SAFETY_SOURCE_ID = "AndroidCellularNetworkSecurity"; private static final String ACTION_LEARN_MORE_ID = "learn_more"; private final Context mContext; private @Nullable TelephonyManager mTelephonyManager; /** * Class constructor of "Cellular Security banner" preference. * * @param context of settings */ public AdaptiveNetworkPreferenceController(@NonNull Context context) { mContext = context; mTelephonyManager = context.getSystemService(TelephonyManager.class); } /** * Adds the controlled preference to the provided preference screen. */ public void addToScreen(@NonNull PreferenceScreen screen) { if (!areNotificationsEnabled()) { // Notification are not enabled for cellular security. return; } if (!isSafetyCenterSupported()) { // SafetyCenter is not supported on the device. return; } SafetyCenterManager safetyCenterManager = mContext.getSystemService( SafetyCenterManager.class); SafetySourceData data = safetyCenterManager.getSafetySourceData( CELLULAR_SECURITY_SAFETY_SOURCE_ID); if (data != null && !data.getIssues().isEmpty()) { for (SafetySourceIssue safetySourceIssue : data.getIssues()) { screen.addPreference(getBannerpreference(safetySourceIssue)); } } } private BannerMessagePreference getBannerpreference(SafetySourceIssue safetySourceIssue) { BannerMessagePreference preference = new BannerMessagePreference(mContext); preference.setOrder(1); preference.setTitle(safetySourceIssue.getTitle()); preference.setSummary(safetySourceIssue.getSummary()); preference.setAttentionLevel(getBannerAttentionLevel(safetySourceIssue.getSeverityLevel())); if (SafetySourceData.SEVERITY_LEVEL_INFORMATION == safetySourceIssue.getSeverityLevel()) { preference.setIcon(R.drawable.ic_info_selector); } for (Action action : safetySourceIssue.getActions()) { if (ACTION_LEARN_MORE_ID.equals(action.getId())) { preference.setNegativeButtonText(action.getLabel()); preference.setNegativeButtonOnClickListener(p -> openLearnMoreLink(action.getPendingIntent())); } } return preference; } @VisibleForTesting protected boolean areNotificationsEnabled() { if (mTelephonyManager == null) { Log.w(TAG, "Telephony manager not yet initialized"); return false; } return mTelephonyManager.isNullCipherNotificationsEnabled() && mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled(); } @VisibleForTesting protected boolean isSafetyCenterSupported() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { return false; } SafetyCenterManager safetyCenterManager = mContext.getSystemService( SafetyCenterManager.class); if (safetyCenterManager == null) { return false; } return safetyCenterManager.isSafetyCenterEnabled(); } private void openLearnMoreLink(PendingIntent intent) { if (intent != null) { mContext.startActivity(intent.getIntent()); } else { Log.w(TAG, "LearnMoreIntent is null"); } } private AttentionLevel getBannerAttentionLevel(int severityLevel) { switch (severityLevel) { case SafetySourceData.SEVERITY_LEVEL_INFORMATION: return AttentionLevel.LOW; case SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION: return AttentionLevel.MEDIUM; case SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING: return AttentionLevel.HIGH; default: return AttentionLevel.NORMAL; } } }
src/com/android/settings/network/telephony/CellularSecuritySettingsFragment.java +18 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package com.android.settings.network.telephony; import android.app.settings.SettingsEnums; import android.content.Context; import android.os.Bundle; import androidx.annotation.NonNull; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; Loading @@ -28,6 +32,19 @@ public class CellularSecuritySettingsFragment extends DashboardFragment { private static final String TAG = "CellularSecuritySettingsFragment"; public static final String KEY_CELLULAR_SECURITY_PREFERENCE = "cellular_security"; private AdaptiveNetworkPreferenceController mAdaptiveNetworkPreferenceController; @Override public void onAttach(@NonNull Context context) { super.onAttach(context); mAdaptiveNetworkPreferenceController = new AdaptiveNetworkPreferenceController(context); } @Override public void onCreatePreferences(@NonNull Bundle savedInstanceState, @NonNull String rootKey) { super.onCreatePreferences(savedInstanceState, rootKey); mAdaptiveNetworkPreferenceController.addToScreen(getPreferenceScreen()); } @Override public int getMetricsCategory() { Loading
tests/robotests/src/com/android/settings/network/telephony/AdaptiveNetworkPreferenceControllerTest.java 0 → 100644 +239 −0 Original line number Diff line number Diff line /* * 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.network.telephony; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.PendingIntent; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Build; import android.safetycenter.SafetyCenterManager; import android.safetycenter.SafetySourceData; import android.safetycenter.SafetySourceIssue; import android.telephony.TelephonyManager; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.settings.R; import com.android.settingslib.widget.BannerMessagePreference; import org.junit.Assume; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import java.util.ArrayList; import java.util.List; @RunWith(AndroidJUnit4.class) public class AdaptiveNetworkPreferenceControllerTest { private static final String CELLULAR_SECURITY_SAFETY_SOURCE_ID = "AndroidCellularNetworkSecurity"; private static final String IDENTIFIER_DISCLOSURE_ISSUE_ID = "identifier_disclosure"; private static final String ACTION_LEARN_MORE_ID = "learn_more"; @Mock private TelephonyManager mTelephonyManager; @Mock private SafetyCenterManager mSafetyCenterManager; @Mock private PreferenceScreen mPreferenceScreen; private Context mContext; private AdaptiveNetworkPreferenceController mController; @Before public void setUp() { MockitoAnnotations.initMocks(this); // Tests must be skipped if these conditions aren't met as they cannot be mocked Assume.assumeTrue(Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU); mContext = spy(ApplicationProvider.getApplicationContext()); when(mContext.getSystemService(SafetyCenterManager.class)).thenReturn(mSafetyCenterManager); when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); mController = new AdaptiveNetworkPreferenceController(mContext); } @Test public void addToScreen_telephonyManagerNotInit() { when(mContext.getSystemService(TelephonyManager.class)).thenReturn(null); mController.addToScreen(mPreferenceScreen); verify(mPreferenceScreen, never()).addPreference(any(BannerMessagePreference.class)); } @Test public void addToScreen_safetyCenterManagerNotInit() { when(mTelephonyManager.isNullCipherNotificationsEnabled()).thenReturn(true); when(mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled()).thenReturn( true); when(mContext.getSystemService(SafetyCenterManager.class)).thenReturn(null); mController.addToScreen(mPreferenceScreen); verify(mPreferenceScreen, never()).addPreference(any(BannerMessagePreference.class)); } @Test public void addToScreen_SafetySourceData_issuesIsEmpty() { when(mSafetyCenterManager.isSafetyCenterEnabled()).thenReturn(true); when(mTelephonyManager.isNullCipherNotificationsEnabled()).thenReturn(true); when(mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled()).thenReturn( true); SafetySourceData data = mock(SafetySourceData.class); when(data.getIssues()).thenReturn(new ArrayList<SafetySourceIssue>()); when(mSafetyCenterManager.getSafetySourceData( CELLULAR_SECURITY_SAFETY_SOURCE_ID)).thenReturn(data); mController.addToScreen(mPreferenceScreen); verify(mPreferenceScreen, never()).addPreference(any(BannerMessagePreference.class)); } @Test public void addToScreen_bannerMessagePreference() { String learMoreTitle = "Learn More"; String IssueTitle = "Title"; String IssueSummary = "Summary"; when(mSafetyCenterManager.isSafetyCenterEnabled()).thenReturn(true); when(mTelephonyManager.isNullCipherNotificationsEnabled()).thenReturn(true); when(mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled()).thenReturn( true); SafetySourceData data = mock(SafetySourceData.class); PendingIntent pendIntent = mock(PendingIntent.class); List<SafetySourceIssue> issues = new ArrayList<>(); SafetySourceIssue.Builder builder = new SafetySourceIssue.Builder( "1", IssueTitle, IssueSummary, SafetySourceData.SEVERITY_LEVEL_INFORMATION, IDENTIFIER_DISCLOSURE_ISSUE_ID); builder.addAction(new SafetySourceIssue.Action.Builder( ACTION_LEARN_MORE_ID, learMoreTitle, pendIntent).build()); issues.add(builder.build()); when(data.getIssues()).thenReturn(issues); when(mSafetyCenterManager.getSafetySourceData( CELLULAR_SECURITY_SAFETY_SOURCE_ID)).thenReturn(data); Drawable drawable = mock(Drawable.class); when(mContext.getDrawable(R.drawable.ic_info_selector)).thenReturn(drawable); BannerMessagePreference[] capturedObject = new BannerMessagePreference[1]; doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { capturedObject[0] = (BannerMessagePreference) invocation.getArguments()[0]; return null; } }).when(mPreferenceScreen).addPreference(any(BannerMessagePreference.class)); mController.addToScreen(mPreferenceScreen); assertThat(capturedObject[0].getOrder()).isEqualTo(1); assertTrue(capturedObject[0].getTitle().toString().contentEquals(IssueTitle)); assertTrue(capturedObject[0].getSummary().toString().contentEquals(IssueSummary)); assertThat(capturedObject[0].getIcon()).isEqualTo(drawable); verify(mPreferenceScreen).addPreference(any(BannerMessagePreference.class)); } @Test public void isSafetyCenterSupported_safetyCenterManagerNotInit() { when(mContext.getSystemService(SafetyCenterManager.class)).thenReturn(null); boolean result = mController.isSafetyCenterSupported(); assertFalse(result); } @Test public void isSafetyCenterSupported_disable() { when(mSafetyCenterManager.isSafetyCenterEnabled()).thenReturn(false); boolean result = mController.isSafetyCenterSupported(); assertFalse(result); } @Test public void isSafetyCenterSupported_enable() { when(mSafetyCenterManager.isSafetyCenterEnabled()).thenReturn(true); boolean result = mController.isSafetyCenterSupported(); assertTrue(result); } @Test public void areNotificationsEnabled_telephonyManagerNotInit() { when(mContext.getSystemService(TelephonyManager.class)).thenReturn(null); boolean result = mController.areNotificationsEnabled(); assertFalse(result); } @Test public void areNotificationsEnabled_telephonyManagerNullCipherDisable() { when(mTelephonyManager.isNullCipherNotificationsEnabled()).thenReturn(false); boolean result = mController.areNotificationsEnabled(); assertFalse(result); } @Test public void areNotificationsEnabled_telephonyManagerIdenfierDiscosureDisable() { when(mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled()).thenReturn( false); boolean result = mController.areNotificationsEnabled(); assertFalse(result); } @Test public void areNotificationsEnabled_enable() { when(mTelephonyManager.isNullCipherNotificationsEnabled()).thenReturn( true); when(mTelephonyManager.isCellularIdentifierDisclosureNotificationsEnabled()).thenReturn( true); boolean result = mController.areNotificationsEnabled(); assertTrue(result); } }