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 @@ -7034,6 +7034,8 @@ + + Account for content @@ -11279,4 +11281,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/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java index 05e37781c70..9766f34cdad 100644 --- a/src/com/android/settings/biometrics/face/FaceSettings.java +++ b/src/com/android/settings/biometrics/face/FaceSettings.java @@ -69,6 +69,8 @@ public class FaceSettings extends DashboardFragment { private Preference mRemoveButton; private Preference mEnrollButton; + private boolean mConfirmingPassword; + private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> { // Disable the toggles until the user re-enrolls @@ -150,9 +152,15 @@ public class FaceSettings extends DashboardFragment { @Override public void onResume() { super.onResume(); - if (mToken == null) { + + if (mToken == null && !mConfirmingPassword) { + // Generate challenge in onResume instead of onCreate, since FaceSettings can be + // created while Keyguard is showing, in which case the resetLockout revokeChallenge + // will invalidate the too-early created challenge here. final long challenge = mFaceManager.generateChallenge(); ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this); + + mConfirmingPassword = true; if (!helper.launchConfirmationActivity(CONFIRM_REQUEST, getString(R.string.security_settings_face_preference_title), null, null, challenge, mUserId)) { @@ -173,6 +181,7 @@ public class FaceSettings extends DashboardFragment { public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == CONFIRM_REQUEST) { + mConfirmingPassword = false; if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) { mFaceManager.setActiveUser(mUserId); // The pin/pattern/password was set. @@ -196,10 +205,18 @@ public class FaceSettings extends DashboardFragment { @Override public void onStop() { super.onStop(); - mToken = null; - final int result = mFaceManager.revokeChallenge(); - if (result < 0) { - Log.w(TAG, "revokeChallenge failed, result: " + result); + + if (!mEnrollController.isClicked() && !getActivity().isChangingConfigurations() + && !mConfirmingPassword) { + // Revoke challenge and finish + if (mToken != null) { + final int result = mFaceManager.revokeChallenge(); + if (result < 0) { + Log.w(TAG, "revokeChallenge failed, result: " + result); + } + mToken = null; + } + getActivity().finish(); } } diff --git a/src/com/android/settings/biometrics/face/FaceSettingsEnrollButtonPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsEnrollButtonPreferenceController.java index ec7b1948fea..a087ccc78e4 100644 --- a/src/com/android/settings/biometrics/face/FaceSettingsEnrollButtonPreferenceController.java +++ b/src/com/android/settings/biometrics/face/FaceSettingsEnrollButtonPreferenceController.java @@ -42,6 +42,7 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference private byte[] mToken; private SettingsActivity mActivity; private Button mButton; + private boolean mIsClicked; public FaceSettingsEnrollButtonPreferenceController(Context context) { this(context, KEY); @@ -63,6 +64,7 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference @Override public void onClick(View v) { + mIsClicked = true; final Intent intent = new Intent(); intent.setClassName("com.android.settings", FaceEnrollIntroduction.class.getName()); intent.putExtra(Intent.EXTRA_USER_ID, mUserId); @@ -83,6 +85,13 @@ public class FaceSettingsEnrollButtonPreferenceController extends BasePreference mToken = token; } + // Return the click state, then clear its state. + public boolean isClicked() { + final boolean wasClicked = mIsClicked; + mIsClicked = false; + return wasClicked; + } + public void setActivity(SettingsActivity activity) { mActivity = activity; } 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/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(); + } }