diff --git a/res/layout/notif_importance_preference.xml b/res/layout/notif_importance_preference.xml index 29c337a699e..44c135b8e49 100644 --- a/res/layout/notif_importance_preference.xml +++ b/res/layout/notif_importance_preference.xml @@ -99,7 +99,7 @@ - Automatically lock + Lock after screen timeout - %1$s after sleep + %1$s after timeout - Immediately after sleep, except when kept unlocked by %1$s + Immediately after timeout, except when kept unlocked by %1$s - %1$s after sleep, except when kept unlocked by %2$s + %1$s after timeout, except when kept unlocked by %2$s Show owner info on lock screen @@ -2829,14 +2829,15 @@ Screen attention - On / Screen won’t turn off if you’re looking at it + On / Screen won\u2019t turn off if you\u2019re looking at it Off - Keep screen on when viewing it + Prevents your screen from turning off if you\u2019re looking at it Screen attention uses the front camera to see if someone is looking at the screen. It works on device, and images are never stored or sent to Google. - + + Keep screen on when viewing it Night Light @@ -7034,6 +7035,8 @@ + + Account for content @@ -11279,4 +11282,12 @@ MMS message + + + Issue with SIM combination + + Using %1$s may limit functionality. Tap to learn more. + + + SIM combination diff --git a/src/com/android/settings/accessibility/VibrationPreferenceFragment.java b/src/com/android/settings/accessibility/VibrationPreferenceFragment.java index 480041a6719..1803a8bafe2 100644 --- a/src/com/android/settings/accessibility/VibrationPreferenceFragment.java +++ b/src/com/android/settings/accessibility/VibrationPreferenceFragment.java @@ -128,6 +128,20 @@ public abstract class VibrationPreferenceFragment extends RadioButtonPickerFragm Settings.System.putInt(getContext().getContentResolver(), vibrationEnabledSetting, vibrationEnabled ? 1 : 0); } + + int previousIntensity = Settings.System.getInt(getContext().getContentResolver(), + getVibrationIntensitySetting(), 0); + if (vibrationEnabled && previousIntensity == candidate.getIntensity()) { + // We can't play preview effect here for all cases because that causes a data + // race (VibratorService may access intensity settings before these settings + // are updated). But we can't just play it in intensity settings update + // observer, because the intensity settings are not changed if we turn the + // vibration off, then on. + // + // In this case we sould play the preview here. + // To be refactored in b/132952771 + playVibrationPreview(); + } } } // There are two conditions that need to change the intensity. @@ -137,15 +151,6 @@ public abstract class VibrationPreferenceFragment extends RadioButtonPickerFragm // Update vibration intensity setting Settings.System.putInt(getContext().getContentResolver(), getVibrationIntensitySetting(), candidate.getIntensity()); - } else { - // We can't play preview effect here for all cases because that causes a data race - // (VibratorService may access intensity settings before these settings are updated). - // But we can't just play it in intensity settings update observer, because the - // intensity settings are not changed if we turn the vibration off, then on. - // - // In this case we sould play the preview here. - // To be refactored in b/132952771 - playVibrationPreview(); } } diff --git a/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java b/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java index b7232744365..fe1d81c17c1 100644 --- a/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java +++ b/src/com/android/settings/applications/appinfo/ExternalSourcesDetails.java @@ -18,6 +18,7 @@ package com.android.settings.applications.appinfo; import static android.app.Activity.RESULT_CANCELED; import static android.app.Activity.RESULT_OK; +import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.settings.SettingsEnums; import android.content.Context; @@ -29,6 +30,7 @@ import androidx.appcompat.app.AlertDialog; import androidx.preference.Preference; import androidx.preference.Preference.OnPreferenceChangeListener; +import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.Settings; import com.android.settings.applications.AppInfoWithHeader; @@ -44,6 +46,7 @@ public class ExternalSourcesDetails extends AppInfoWithHeader private AppStateInstallAppsBridge mAppBridge; private AppOpsManager mAppOpsManager; + private ActivityManager mActivityManager; private UserManager mUserManager; private RestrictedSwitchPreference mSwitchPref; private InstallAppsState mInstallAppsState; @@ -55,6 +58,7 @@ public class ExternalSourcesDetails extends AppInfoWithHeader final Context context = getActivity(); mAppBridge = new AppStateInstallAppsBridge(context, mState, null); mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + mActivityManager = context.getSystemService(ActivityManager.class); mUserManager = UserManager.get(context); addPreferencesFromResource(R.xml.external_sources_details); @@ -99,10 +103,21 @@ public class ExternalSourcesDetails extends AppInfoWithHeader : R.string.app_permission_summary_not_allowed); } - private void setCanInstallApps(boolean newState) { + @VisibleForTesting + void setCanInstallApps(boolean newState) { mAppOpsManager.setMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, mPackageInfo.applicationInfo.uid, mPackageName, newState ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_ERRORED); + if (!newState) { + killApp(mPackageInfo.applicationInfo.uid); + } + } + + private void killApp(int uid) { + if (UserHandle.isCore(uid)) { + return; + } + mActivityManager.killUid(uid, "User denied OP_REQUEST_INSTALL_PACKAGES"); } @Override diff --git a/src/com/android/settings/display/ColorModePreferenceFragment.java b/src/com/android/settings/display/ColorModePreferenceFragment.java index c28de731ffe..873653223be 100644 --- a/src/com/android/settings/display/ColorModePreferenceFragment.java +++ b/src/com/android/settings/display/ColorModePreferenceFragment.java @@ -213,5 +213,12 @@ public class ColorModePreferenceFragment extends RadioButtonPickerFragment { sir.xmlResId = R.xml.color_mode_settings; return Arrays.asList(sir); } + + @Override + protected boolean isPageSearchEnabled(Context context) { + final int[] availableColorModes = context.getResources().getIntArray( + com.android.internal.R.array.config_availableColorModes); + return availableColorModes != null && availableColorModes.length > 0; + } }; } diff --git a/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSlice.java b/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSlice.java index 2c091fa716c..0e96b05c20d 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSlice.java +++ b/src/com/android/settings/homepage/contextualcards/slices/ContextualAdaptiveSleepSlice.java @@ -80,7 +80,8 @@ public class ContextualAdaptiveSleepSlice implements CustomSliceable { final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_settings_adaptive_sleep); final CharSequence title = mContext.getText(R.string.adaptive_sleep_title); - final CharSequence subtitle = mContext.getText(R.string.adaptive_sleep_description); + final CharSequence subtitle = mContext.getText( + R.string.adaptive_sleep_contextual_slice_summary); final SliceAction pAction = SliceAction.createDeeplink(getPrimaryAction(), icon, diff --git a/src/com/android/settings/notification/ImportancePreference.java b/src/com/android/settings/notification/ImportancePreference.java index 3e81d0cd06c..b059f9165e7 100644 --- a/src/com/android/settings/notification/ImportancePreference.java +++ b/src/com/android/settings/notification/ImportancePreference.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; import android.transition.AutoTransition; +import android.transition.Transition; import android.transition.TransitionManager; import android.util.AttributeSet; import android.view.View; @@ -112,6 +113,7 @@ public class ImportancePreference extends Preference { mAlertButton.setEnabled(false); } + setImportanceSummary((ViewGroup) holder.itemView, mImportance, false); switch (mImportance) { case IMPORTANCE_MIN: case IMPORTANCE_LOW: @@ -126,23 +128,29 @@ public class ImportancePreference extends Preference { mAlertButton.setSelected(true); break; } - setImportanceSummary((ViewGroup) holder.itemView, mImportance, false); mSilenceButton.setOnClickListener(v -> { callChangeListener(IMPORTANCE_LOW); mAlertButton.setBackground(unselectedBackground); - mAlertButton.setSelected(false); mSilenceButton.setBackground(selectedBackground); - mSilenceButton.setSelected(true); setImportanceSummary((ViewGroup) holder.itemView, IMPORTANCE_LOW, true); + // a11y service won't always read the newly appearing text in the right order if the + // selection happens too soon (readback happens on a different thread as layout). post + // the selection to make that conflict less likely + holder.itemView.post(() -> { + mAlertButton.setSelected(false); + mSilenceButton.setSelected(true); + }); }); mAlertButton.setOnClickListener(v -> { callChangeListener(IMPORTANCE_DEFAULT); mSilenceButton.setBackground(unselectedBackground); - mSilenceButton.setSelected(false); mAlertButton.setBackground(selectedBackground); - mAlertButton.setSelected(true); setImportanceSummary((ViewGroup) holder.itemView, IMPORTANCE_DEFAULT, true); + holder.itemView.post(() -> { + mSilenceButton.setSelected(false); + mAlertButton.setSelected(true); + }); }); } @@ -172,9 +180,7 @@ public class ImportancePreference extends Preference { ((ImageView) parent.findViewById(R.id.alert_icon)).setImageTintList(colorAccent); ((TextView) parent.findViewById(R.id.alert_label)).setTextColor(colorAccent); - TextView view = parent.findViewById(R.id.alert_summary); - view.setText(R.string.notification_channel_summary_default); - view.setVisibility(VISIBLE); + parent.findViewById(R.id.alert_summary).setVisibility(VISIBLE); } else { parent.findViewById(R.id.alert_summary).setVisibility(GONE); ((ImageView) parent.findViewById(R.id.alert_icon)).setImageTintList(colorNormal); @@ -182,9 +188,7 @@ public class ImportancePreference extends Preference { ((ImageView) parent.findViewById(R.id.silence_icon)).setImageTintList(colorAccent); ((TextView) parent.findViewById(R.id.silence_label)).setTextColor(colorAccent); - TextView view = parent.findViewById(R.id.silence_summary); - view.setVisibility(VISIBLE); - view.setText(R.string.notification_channel_summary_low); + parent.findViewById(R.id.silence_summary).setVisibility(VISIBLE); } } } diff --git a/src/com/android/settings/sim/SimSelectNotification.java b/src/com/android/settings/sim/SimSelectNotification.java index d228b6ea0c1..a303e426c57 100644 --- a/src/com/android/settings/sim/SimSelectNotification.java +++ b/src/com/android/settings/sim/SimSelectNotification.java @@ -24,6 +24,10 @@ import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELE import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL; import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA; import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE; +import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_NAMES; +import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_WARNING_TYPE; +import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA; +import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE; import static android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID; import static android.telephony.data.ApnSetting.TYPE_MMS; @@ -43,6 +47,7 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.network.telephony.MobileNetworkActivity; +import com.android.settingslib.HelpUtils; public class SimSelectNotification extends BroadcastReceiver { private static final String TAG = "SimSelectNotification"; @@ -50,6 +55,8 @@ public class SimSelectNotification extends BroadcastReceiver { public static final int SIM_SELECT_NOTIFICATION_ID = 1; @VisibleForTesting public static final int ENABLE_MMS_NOTIFICATION_ID = 2; + @VisibleForTesting + public static final int SIM_WARNING_NOTIFICATION_ID = 3; @VisibleForTesting public static final String SIM_SELECT_NOTIFICATION_CHANNEL = @@ -59,6 +66,10 @@ public class SimSelectNotification extends BroadcastReceiver { public static final String ENABLE_MMS_NOTIFICATION_CHANNEL = "enable_mms_notification_channel"; + @VisibleForTesting + public static final String SIM_WARNING_NOTIFICATION_CHANNEL = + "sim_warning_notification_channel"; + @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); @@ -125,13 +136,23 @@ public class SimSelectNotification extends BroadcastReceiver { } private void onPrimarySubscriptionListChanged(Context context, Intent intent) { + startSimSelectDialogIfNeeded(context, intent); + sendSimCombinationWarningIfNeeded(context, intent); + } + + private void startSimSelectDialogIfNeeded(Context context, Intent intent) { + int dialogType = intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, + EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE); + + if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE) { + return; + } + // Cancel any previous notifications cancelSimSelectNotification(context); // Create a notification to tell the user that some defaults are missing createSimSelectNotification(context); - int dialogType = intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, - EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE); if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL) { int subId = intent.getIntExtra(EXTRA_SUBSCRIPTION_ID, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); @@ -139,11 +160,12 @@ public class SimSelectNotification extends BroadcastReceiver { // If there is only one subscription, ask if user wants to use if for everything Intent newIntent = new Intent(context, SimDialogActivity.class); newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, SimDialogActivity.PREFERRED_PICK); + newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, + SimDialogActivity.PREFERRED_PICK); newIntent.putExtra(SimDialogActivity.PREFERRED_SIM, slotIndex); context.startActivity(newIntent); } else if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA) { - // If there are mulitple, ensure they pick default data + // If there are multiple, ensure they pick default data Intent newIntent = new Intent(context, SimDialogActivity.class); newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, SimDialogActivity.DATA_PICK); @@ -151,6 +173,18 @@ public class SimSelectNotification extends BroadcastReceiver { } } + private void sendSimCombinationWarningIfNeeded(Context context, Intent intent) { + final int warningType = intent.getIntExtra(EXTRA_SIM_COMBINATION_WARNING_TYPE, + EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE); + + if (warningType == EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA) { + // Cancel any previous notifications + cancelSimCombinationWarningNotification(context); + // Create a notification to tell the user that some defaults are missing + createSimCombinationWarningNotification(context, intent); + } + } + private void createSimSelectNotification(Context context){ final Resources resources = context.getResources(); @@ -222,4 +256,52 @@ public class SimSelectNotification extends BroadcastReceiver { (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.cancel(ENABLE_MMS_NOTIFICATION_ID); } + + private void createSimCombinationWarningNotification(Context context, Intent intent){ + final Resources resources = context.getResources(); + final String simNames = intent.getStringExtra(EXTRA_SIM_COMBINATION_NAMES); + + if (simNames == null) { + return; + } + + CharSequence dualCdmaSimWarningSummary = resources.getString( + R.string.dual_cdma_sim_warning_notification_summary, simNames); + + NotificationChannel notificationChannel = new NotificationChannel( + SIM_WARNING_NOTIFICATION_CHANNEL, + resources.getText(R.string.dual_cdma_sim_warning_notification_channel_title), + NotificationManager.IMPORTANCE_HIGH); + + Notification.Builder builder = + new Notification.Builder(context, SIM_WARNING_NOTIFICATION_CHANNEL) + .setSmallIcon(R.drawable.ic_sim_card_alert_white_48dp) + .setColor(context.getColor(R.color.sim_noitification)) + .setContentTitle(resources.getText( + R.string.sim_combination_warning_notification_title)) + .setContentText(dualCdmaSimWarningSummary) + .setStyle(new Notification.BigTextStyle().bigText( + dualCdmaSimWarningSummary)) + .setAutoCancel(true); + + // Create the pending intent that will lead to the helper page. + Intent resultIntent = HelpUtils.getHelpIntent( + context, + context.getString(R.string.help_uri_sim_combination_warning), + context.getClass().getName()); + PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent, + PendingIntent.FLAG_CANCEL_CURRENT); + builder.setContentIntent(resultPendingIntent); + + NotificationManager notificationManager = + context.getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(notificationChannel); + notificationManager.notify(SIM_WARNING_NOTIFICATION_ID, builder.build()); + } + + public static void cancelSimCombinationWarningNotification(Context context) { + NotificationManager notificationManager = + context.getSystemService(NotificationManager.class); + notificationManager.cancel(SIM_WARNING_NOTIFICATION_ID); + } } diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/ExternalSourcesDetailsTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/ExternalSourcesDetailsTest.java index 10c2675be82..002a0bc5350 100644 --- a/tests/robotests/src/com/android/settings/applications/appinfo/ExternalSourcesDetailsTest.java +++ b/tests/robotests/src/com/android/settings/applications/appinfo/ExternalSourcesDetailsTest.java @@ -19,11 +19,17 @@ package com.android.settings.applications.appinfo; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.ActivityManager; +import android.app.AppOpsManager; import android.content.Context; import android.content.ContextWrapper; import android.content.pm.ApplicationInfo; @@ -55,6 +61,10 @@ public class ExternalSourcesDetailsTest { @Mock private UserManager mUserManager; @Mock + private ActivityManager mActivityManager; + @Mock + private AppOpsManager mAppOpsManager; + @Mock private RestrictedSwitchPreference mSwitchPref; @Mock private RestrictedPreferenceHelper mHelper; @@ -69,9 +79,46 @@ public class ExternalSourcesDetailsTest { mFragment = new ExternalSourcesDetails(); ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager); + ReflectionHelpers.setField(mFragment, "mActivityManager", mActivityManager); + ReflectionHelpers.setField(mFragment, "mAppOpsManager", mAppOpsManager); ReflectionHelpers.setField(mFragment, "mSwitchPref", mSwitchPref); } + @Test + public void setCanInstallApps_false_shouldKillNonCoreUid() { + int mockUid = 23456; + ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo); + + mPackageInfo.applicationInfo = new ApplicationInfo(); + mPackageInfo.applicationInfo.uid = mockUid; + assertThat(UserHandle.isCore(mockUid)).isFalse(); + mFragment.setCanInstallApps(false); + verify(mActivityManager).killUid(eq(mockUid), anyString()); + } + + @Test + public void setCanInstallApps_false_shouldNotKillCoreUid() { + int mockUid = 1234; + ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo); + + mPackageInfo.applicationInfo = new ApplicationInfo(); + mPackageInfo.applicationInfo.uid = mockUid; + assertThat(UserHandle.isCore(mockUid)).isTrue(); + mFragment.setCanInstallApps(false); + verify(mActivityManager, never()).killUid(eq(mockUid), anyString()); + } + + @Test + public void setCanInstallApps_true_shouldNotKillUid() { + int mockUid = 23456; + ReflectionHelpers.setField(mFragment, "mPackageInfo", mPackageInfo); + + mPackageInfo.applicationInfo = new ApplicationInfo(); + mPackageInfo.applicationInfo.uid = mockUid; + mFragment.setCanInstallApps(true); + verify(mActivityManager, never()).killUid(eq(mockUid), anyString()); + } + @Test public void refreshUi_noPackageInfo_shouldReturnFalseAndNoCrash() { mFragment.refreshUi(); diff --git a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java index 69c0919719f..5a2dd48c3c5 100644 --- a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java +++ b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java @@ -21,10 +21,15 @@ import static android.provider.Settings.ENABLE_MMS_DATA_REQUEST_REASON_INCOMING_ import static android.provider.Settings.ENABLE_MMS_DATA_REQUEST_REASON_OUTGOING_MMS; import static android.provider.Settings.EXTRA_ENABLE_MMS_DATA_REQUEST_REASON; import static android.provider.Settings.EXTRA_SUB_ID; +import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_NAMES; +import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_WARNING_TYPE; +import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA; import static android.telephony.data.ApnSetting.TYPE_MMS; import static com.android.settings.sim.SimSelectNotification.ENABLE_MMS_NOTIFICATION_CHANNEL; import static com.android.settings.sim.SimSelectNotification.ENABLE_MMS_NOTIFICATION_ID; +import static com.android.settings.sim.SimSelectNotification.SIM_WARNING_NOTIFICATION_CHANNEL; +import static com.android.settings.sim.SimSelectNotification.SIM_WARNING_NOTIFICATION_ID; import static com.google.common.truth.Truth.assertThat; @@ -76,10 +81,16 @@ public class SimSelectNotificationTest { @Mock private Resources mResources; - private String mFakeOperatorName = "fake_operator_name"; - private CharSequence mFakeNotificationChannelTitle = "fake_notification_channel_title"; - private CharSequence mFakeNotificationTitle = "fake_notification_title"; - private String mFakeNotificationSummary = "fake_notification_Summary"; + private final String mFakeOperatorName = "fake_operator_name"; + private final CharSequence mFakeNotificationChannelTitle = "fake_notification_channel_title"; + private final CharSequence mFakeNotificationTitle = "fake_notification_title"; + private final String mFakeNotificationSummary = "fake_notification_Summary"; + + // Dual CDMA combination notification. + private final String mFakeDualCdmaWarningChannelTitle = "fake_dual_cdma_warning_channel_title"; + private final String mFakeDualCdmaWarningTitle = "fake_dual_cdma_warning_title"; + private final String mFakeDualCdmaWarningSummary = "fake_dual_cdma_warning_summary"; + private final String mSimCombinationName = " carrier1 & carrier 2"; private int mSubId = 1; @@ -90,6 +101,8 @@ public class SimSelectNotificationTest { MockitoAnnotations.initMocks(this); when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)) .thenReturn(mNotificationManager); + when(mContext.getSystemService(NotificationManager.class)) + .thenReturn(mNotificationManager); when(mContext.getSystemService(Context.TELEPHONY_SERVICE)) .thenReturn(mTelephonyManager); when(mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)) @@ -111,6 +124,13 @@ public class SimSelectNotificationTest { .thenReturn(mFakeNotificationChannelTitle); when(mResources.getString(R.string.enable_mms_notification_summary, mFakeOperatorName)).thenReturn(mFakeNotificationSummary); + + when(mResources.getText(R.string.dual_cdma_sim_warning_notification_channel_title)) + .thenReturn(mFakeDualCdmaWarningChannelTitle); + when(mResources.getText(R.string.sim_combination_warning_notification_title)) + .thenReturn(mFakeDualCdmaWarningTitle); + when(mResources.getString(R.string.dual_cdma_sim_warning_notification_summary, + mSimCombinationName)).thenReturn(mFakeDualCdmaWarningSummary); } @Test @@ -162,5 +182,43 @@ public class SimSelectNotificationTest { mSimSelectNotification.onReceive(mContext, intent); verify(mNotificationManager, never()).createNotificationChannel(any()); } + + @Test + public void onReceivePrimarySubListChange_NoExtra_notificationShouldNotSend() { + Intent intent = new Intent(TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED); + + // EXTRA_SUB_ID and EXTRA_ENABLE_MMS_DATA_REQUEST_REASON are required. + mSimSelectNotification.onReceive(mContext, intent); + verify(mNotificationManager, never()).createNotificationChannel(any()); + } + + @Test + public void onReceivePrimarySubListChange_DualCdmaWarning_notificationShouldSend() { + Intent intent = new Intent(TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED); + + intent.putExtra(EXTRA_SIM_COMBINATION_NAMES, mSimCombinationName); + intent.putExtra(EXTRA_SIM_COMBINATION_WARNING_TYPE, + EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA); + + mSimSelectNotification.onReceive(mContext, intent); + + // Capture the notification channel created and verify its fields. + ArgumentCaptor nc = ArgumentCaptor.forClass(NotificationChannel.class); + verify(mNotificationManager).createNotificationChannel(nc.capture()); + + assertThat(nc.getValue().getId()).isEqualTo(SIM_WARNING_NOTIFICATION_CHANNEL); + assertThat(nc.getValue().getName()).isEqualTo(mFakeDualCdmaWarningChannelTitle); + assertThat(nc.getValue().getImportance()).isEqualTo(IMPORTANCE_HIGH); + + // Capture the notification it notifies and verify its fields. + ArgumentCaptor notification = ArgumentCaptor.forClass(Notification.class); + verify(mNotificationManager).notify( + eq(SIM_WARNING_NOTIFICATION_ID), notification.capture()); + assertThat(notification.getValue().extras.getCharSequence(Notification.EXTRA_TITLE)) + .isEqualTo(mFakeDualCdmaWarningTitle); + assertThat(notification.getValue().extras.getCharSequence(Notification.EXTRA_BIG_TEXT)) + .isEqualTo(mFakeDualCdmaWarningSummary); + assertThat(notification.getValue().contentIntent).isNotNull(); + } }