Merge "Add null check before calling parsePhoneNumber" into main
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index fca54e4..3b0d6b9 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -2370,8 +2370,23 @@
                 PackageManager pm = context.getPackageManager();
                 pm = context.createContextAsUser(UserHandle.CURRENT, 0).getPackageManager();
                 if (userManager.isUserUnlocked()) {
-                    context.startActivityAsUser(pm.getLaunchIntentForPackage(
-                            Telephony.Sms.getDefaultSmsPackage(context)), UserHandle.CURRENT);
+                    String defaultSmsPackage = Telephony.Sms.getDefaultSmsPackage(context);
+                    if (defaultSmsPackage == null) {
+                        Rlog.e("InboundSmsHandler",
+                                "NewMessageNotificationActionReceiver: failed to launch default "
+                                        + "sms app, default sms package is null");
+                        return;
+                    }
+                    Intent launchIntent = pm.getLaunchIntentForPackage(defaultSmsPackage);
+                    if (launchIntent == null) {
+                        Rlog.e("InboundSmsHandler",
+                                "NewMessageNotificationActionReceiver: failed to get launch "
+                                        + "intent for "
+                                        + defaultSmsPackage);
+                        return;
+                    }
+                    context.startActivityAsUser(launchIntent, UserHandle.CURRENT);
+
                 }
             }
         }
@@ -2461,4 +2476,15 @@
                 SmsBroadcastReceiver resultReceiver, boolean userUnlocked, boolean block,
                 List<SmsFilter> remainingFilters);
     }
+
+    /**
+     * Creates a new instance of the private {@code NewMessageNotificationActionReceiver} for
+     * testing.
+     *
+     * @return A new instance of {@code NewMessageNotificationActionReceiver}.
+     */
+    @VisibleForTesting
+    public BroadcastReceiver makeNewMessageNotificationActionReceiver() {
+        return new NewMessageNotificationActionReceiver();
+    }
 }
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index c72ca8c..f9f37aa 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -3255,7 +3255,7 @@
             if (mFeatureFlags.satellite25q4Apis()
                     && result == SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY
                     && tracker.mRetryCount >= getMaxSmsRetryCount()) {
-                resultForMetrics = SmsManager.RESULT_SMS_SEND_FAIL_AFTER_MAX_RETRY;
+                resultForMetrics = SmsManager.RESULT_SMS_SEND_FAILED_AFTER_MAX_RETRY;
             }
 
             mPhone.getSmsStats().onOutgoingSms(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
index 5affa6e..c085556 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.atLeastOnce;
@@ -40,6 +41,7 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
@@ -107,6 +109,8 @@
     private GsmInboundSmsHandler mGsmInboundSmsHandler;
 
     private FakeSmsContentProvider mContentProvider;
+    private UserManager mUserManager;
+    private ContentResolver mContentResolver;
     private static final String RAW_TABLE_NAME = "raw";
     private static final Uri sRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI,
             RAW_TABLE_NAME);
@@ -166,6 +170,9 @@
         mCdmaInboundSmsHandler = Mockito.mock(CdmaInboundSmsHandler.class);
         mSmsFilter = Mockito.mock(InboundSmsHandler.SmsFilter.class);
         mSmsFilter2 = Mockito.mock(InboundSmsHandler.SmsFilter.class);
+        mUserManager = Mockito.mock(UserManager.class);
+        ContentResolver resolver = mContext.getContentResolver();
+        mContentResolver = Mockito.spy(resolver);
 
         when(mFeatureFlags.smsMmsDeliverBroadcastsRedirectToMainUser()).thenReturn(true);
         doReturn(true).when(mTelephonyManager).getSmsReceiveCapableForPhone(anyInt(), anyBoolean());
@@ -1309,5 +1316,42 @@
         transitionFromStartupToIdle();
         assertTrue(mGsmInboundSmsHandler.setImsManager(imsManager));
     }
+
+    @Test
+    public void testNewMessageNotification_nullLaunchIntent_doesNotCrash() {
+        BroadcastReceiver receiver =
+                mGsmInboundSmsHandler.makeNewMessageNotificationActionReceiver();
+
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mUserManager.isUserUnlocked()).thenReturn(true);
+
+        // getLaunchIntentForPackage returns null
+        when(mPackageManager.getLaunchIntentForPackage(anyString())).thenReturn(null);
+        Intent intent = new Intent("com.android.internal.telephony.OPEN_DEFAULT_SMS_APP");
+
+        transitionFromStartupToIdle();
+        receiver.onReceive(mContext, intent);
+
+        // There should not happen the invocation for below method, nor exception
+        verify(mContext, never()).startActivityAsUser(any(Intent.class), any(UserHandle.class));
+    }
+
+    @Test
+    public void testNewMessageNotification_nullSmsPackage_doesNotCrash() {
+        transitionFromStartupToIdle();
+
+        BroadcastReceiver receiver =
+                mGsmInboundSmsHandler.makeNewMessageNotificationActionReceiver();
+
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mUserManager.isUserUnlocked()).thenReturn(true);
+        // ContentResolver returns null for the default package name for the SMS
+        Intent intent = new Intent("com.android.internal.telephony.OPEN_DEFAULT_SMS_APP");
+        receiver.onReceive(mContext, intent);
+
+        // There should not happen the invocation for below method, nor exception
+        verify(mContext, never()).startActivityAsUser(any(Intent.class), any(UserHandle.class));
+    }
 }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
index 2854e01..0688505 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
@@ -804,7 +804,7 @@
                 anyBoolean(),
                 eq(false),
                 anyBoolean(),
-                eq(SmsManager.RESULT_SMS_SEND_FAIL_AFTER_MAX_RETRY),    // resultCode
+                eq(SmsManager.RESULT_SMS_SEND_FAILED_AFTER_MAX_RETRY),    // resultCode
                 eq(SmsResponse.NO_ERROR_CODE),
                 eq(messageId),
                 eq(true),